* Copyright (c) 2021-2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "battery_notify.h"
#include <regex>
#ifdef BATTERY_MANAGER_ENABLE_CHARGING_SOUND
#include "ffrt_utils.h"
#ifdef CONFIG_USE_JEMALLOC_DFX_INTF
#include "memory_guard.h"
#endif
#endif
#ifdef BATTERY_MANAGER_ENABLE_CHARGING_SOUND
#include "ability_manager_client.h"
#include "ability_manager_proxy.h"
#include "config_policy_utils.h"
#endif
#include "common_event_data.h"
#include "common_event_manager.h"
#include "common_event_publish_info.h"
#include "common_event_support.h"
#include "errors.h"
#ifdef HAS_HIVIEWDFX_HISYSEVENT_PART
#include "hisysevent.h"
#endif
#include "if_system_ability_manager.h"
#include "iservice_registry.h"
#include "string_ex.h"
#include "system_ability_definition.h"
#include <hookmgr.h>
#include "battery_hookmgr.h"
#include "battery_config.h"
#include "battery_log.h"
#include "battery_service.h"
#include "power_vibrator.h"
#include "power_mgr_client.h"
#include <dlfcn.h>
using namespace OHOS::AAFwk;
using namespace OHOS::EventFwk;
#ifdef HAS_HIVIEWDFX_HISYSEVENT_PART
using namespace OHOS::HiviewDFX;
#endif
namespace OHOS {
namespace PowerMgr {
bool g_batteryLowOnce = false;
bool g_batteryOkOnce = false;
bool g_batteryConnectOnce = false;
bool g_batteryDisconnectOnce = false;
bool g_batteryChargingOnce = false;
bool g_batteryDischargingOnce = false;
bool g_commonEventInitSuccess = false;
OHOS::PowerMgr::BatteryCapacityLevel g_lastCapacityLevel = OHOS::PowerMgr::BatteryCapacityLevel::LEVEL_NONE;
const std::string POWER_SUPPLY = "SUBSYSTEM=power_supply";
const std::string SHUTDOWN = "shutdown";
const std::string REBOOT = "reboot";
const std::string SEND_COMMONEVENT = "sendcommonevent";
const std::string SEND_CUSTOMEVENT = "sendcustomevent";
const std::string SEND_POPUP = "sendpopup";
const std::string BATTERY_CUSTOM_EVENT_PREFIX = "usual.event.battery";
const std::string PRODUCT_TYPE_THREE = "RVS_ADAPTER_PRODUCT_TYPE=3";
const std::string PRODUCT_TYPE_FOUR = "RVS_ADAPTER_PRODUCT_TYPE=4";
const std::string PRODUCT_TYPE_FIVE = "RVS_ADAPTER_PRODUCT_TYPE=5";
sptr<BatteryService> g_service = DelayedSpSingleton<BatteryService>::GetInstance();
BatteryNotify::BatteryNotify()
{
const int32_t DEFAULT_LOW_CAPACITY = 20;
lowCapacity_ = BatteryConfig::GetInstance().GetInt("soc.low", DEFAULT_LOW_CAPACITY);
BATTERY_HILOGI(COMP_SVC, "Low broadcast power=%{public}d", lowCapacity_);
}
int32_t BatteryNotify::PublishEvents(BatteryInfo& info)
{
if (!g_commonEventInitSuccess) {
if (!IsCommonEventServiceAbilityExist()) {
return ERR_NO_INIT;
}
}
if (info.GetUevent() != POWER_SUPPLY && info.GetUevent() != "" &&
info.GetUevent() != INVALID_STRING_VALUE) {
HandleUevent(info);
return ERR_OK;
}
bool isAllSuccess = true;
bool ret = PublishChangedEvent(info);
isAllSuccess &= ret;
ret = PublishChangedEventInner(info);
isAllSuccess &= ret;
std::lock_guard<std::mutex> lock(mutex_);
ret = PublishLowEvent(info);
isAllSuccess &= ret;
ret = PublishOkayEvent(info);
isAllSuccess &= ret;
#ifdef BATTERY_MANAGER_ENABLE_WIRELESS_CHARGE
PublishEventContext context {.pluggedType = info.GetPluggedType(),
.lastPluggedType = lastPowerPluggedType_,
.wirelessChargerEnable = BatteryConfig::GetInstance().GetWirelessChargerConf()};
HookMgrExecute(
GetBatteryHookMgr(), static_cast<int32_t>(BatteryHookStage::BATTERY_PUBLISH_EVENT), &context, nullptr);
#endif
ret = PublishPowerConnectedEvent(info);
isAllSuccess &= ret;
ret = PublishPowerDisconnectedEvent(info);
isAllSuccess &= ret;
ret = PublishChargingEvent(info);
isAllSuccess &= ret;
ret = PublishDischargingEvent(info);
isAllSuccess &= ret;
ret = PublishChargeTypeChangedEvent(info);
isAllSuccess &= ret;
lastPowerPluggedType_ = info.GetPluggedType();
return isAllSuccess ? ERR_OK : ERR_NO_INIT;
}
void BatteryNotify::HandleUevent(BatteryInfo& info)
{
std::string uevent = info.GetUevent();
auto pos = uevent.rfind('$');
if (pos != std::string::npos) {
std::string ueventName = uevent.substr(0, pos);
std::string ueventAct = uevent.substr(++pos);
BATTERY_HILOGI(COMP_SVC, "%{public}s decision %{public}s",
ueventName.c_str(), ueventAct.c_str());
if (ueventAct == SHUTDOWN) {
const std::string reason = "POWEROFF_CHARGE_DISABLE";
PowerMgrClient::GetInstance().ShutDownDevice(reason);
} else if (ueventAct == REBOOT) {
PowerMgrClient::GetInstance().RebootDevice(ueventName);
} else if (ueventAct == SEND_COMMONEVENT) {
info.SetUevent(ueventName);
PublishChangedEvent(info);
} else if (ueventAct.compare(0, BATTERY_CUSTOM_EVENT_PREFIX.size(), BATTERY_CUSTOM_EVENT_PREFIX) == 0) {
info.SetUevent(ueventName);
PublishCustomEvent(info, ueventAct);
if (ueventName == PRODUCT_TYPE_THREE || ueventName == PRODUCT_TYPE_FOUR
|| ueventName == PRODUCT_TYPE_FIVE) {
HandleNotification(ueventName);
}
} else if (ueventAct == SEND_POPUP) {
info.SetUevent(ueventName);
PublishChangedEvent(info);
HandleNotification(ueventName);
} else {
BATTERY_HILOGE(COMP_SVC, "undefine uevent act %{public}s", ueventAct.c_str());
}
}
BATTERY_HILOGI(COMP_SVC, "handle uevent info %{public}s", uevent.c_str());
}
bool BatteryNotify::PublishChargeTypeChangedEvent(const BatteryInfo& info)
{
ChargeType chargeType = info.GetChargeType();
bool isSuccess = true;
if (batteryInfoChargeType_ == chargeType) {
BATTERY_HILOGD(COMP_SVC, "No need to send chargetype event");
return isSuccess;
}
batteryInfoChargeType_ = chargeType;
Want want;
want.SetAction(CommonEventSupport::COMMON_EVENT_CHARGE_TYPE_CHANGED);
CommonEventData data;
data.SetWant(want);
CommonEventPublishInfo publishInfo;
publishInfo.SetOrdered(false);
data.SetCode(static_cast<int32_t>(chargeType));
BATTERY_HILOGD(COMP_SVC, "publisher chargeType=%{public}d", chargeType);
isSuccess = CommonEventManager::PublishCommonEvent(data, publishInfo);
if (!isSuccess) {
BATTERY_HILOGD(COMP_SVC, "failed to publish battery charge type event");
}
return isSuccess;
}
bool BatteryNotify::IsCommonEventServiceAbilityExist() const
{
sptr<ISystemAbilityManager> sysMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
if (!sysMgr) {
BATTERY_HILOGE(COMP_SVC,
"IsCommonEventServiceAbilityExist Get ISystemAbilityManager failed, no SystemAbilityManager");
return false;
}
sptr<IRemoteObject> remote = sysMgr->CheckSystemAbility(COMMON_EVENT_SERVICE_ID);
if (!remote) {
BATTERY_HILOGE(COMP_SVC, "No CesServiceAbility");
return false;
}
if (!g_commonEventInitSuccess) {
BATTERY_HILOGI(COMP_SVC, "common event service ability init success");
g_commonEventInitSuccess = true;
}
return true;
}
bool BatteryNotify::PublishChangedEvent(const BatteryInfo& info)
{
Want want;
int32_t capacity = info.GetCapacity();
int32_t pluggedType = static_cast<int32_t>(info.GetPluggedType());
int32_t temperature = info.GetTemperature();
int32_t healthState = static_cast<int32_t>(info.GetHealthState());
want.SetParam(BatteryInfo::COMMON_EVENT_KEY_CAPACITY, capacity);
want.SetParam(BatteryInfo::COMMON_EVENT_KEY_VOLTAGE, info.GetVoltage());
want.SetParam(BatteryInfo::COMMON_EVENT_KEY_TEMPERATURE, temperature);
want.SetParam(BatteryInfo::COMMON_EVENT_KEY_HEALTH_STATE, healthState);
want.SetParam(BatteryInfo::COMMON_EVENT_KEY_PLUGGED_TYPE, pluggedType);
want.SetParam(BatteryInfo::COMMON_EVENT_KEY_CHARGE_STATE, static_cast<int32_t>(info.GetChargeState()));
want.SetParam(BatteryInfo::COMMON_EVENT_KEY_PRESENT, info.IsPresent());
want.SetParam(BatteryInfo::COMMON_EVENT_KEY_TECHNOLOGY, info.GetTechnology());
want.SetParam(BatteryInfo::COMMON_EVENT_KEY_UEVENT, info.GetUevent());
auto capacityLevel = static_cast<uint32_t>(BatteryCapacityLevel::LEVEL_NONE);
g_service->GetCapacityLevel(capacityLevel);
if (static_cast<BatteryCapacityLevel>(capacityLevel) != g_lastCapacityLevel) {
want.SetParam(BatteryInfo::COMMON_EVENT_KEY_CAPACITY_LEVEL, static_cast<int32_t>(capacityLevel));
g_lastCapacityLevel = static_cast<BatteryCapacityLevel>(capacityLevel);
}
want.SetAction(CommonEventSupport::COMMON_EVENT_BATTERY_CHANGED);
CommonEventData data;
data.SetWant(want);
CommonEventPublishInfo publishInfo;
publishInfo.SetOrdered(false);
if (capacity != lastCapacity_ || pluggedType != lastPluggedType_ ||
temperature != lastTemperature_ || healthState != lastHealthState_) {
#ifdef HAS_HIVIEWDFX_HISYSEVENT_PART
HiSysEventWrite(HiSysEvent::Domain::BATTERY, "CHANGED", HiSysEvent::EventType::STATISTIC,
"LEVEL", capacity, "CHARGER", pluggedType, "VOLTAGE", info.GetVoltage(),
"TEMPERATURE", temperature, "HEALTH", healthState, "CURRENT", info.GetNowCurrent(),
"CHARGE_MODE", static_cast<int32_t>(info.GetChargeType()));
#endif
lastCapacity_ = capacity;
lastPluggedType_ = pluggedType;
lastTemperature_ = temperature;
lastHealthState_ = healthState;
}
bool isSuccess = CommonEventManager::PublishCommonEvent(data, publishInfo);
if (!isSuccess) {
BATTERY_HILOGE(FEATURE_BATT_INFO, "failed to publish BATTERY_CHANGED event");
}
return isSuccess;
}
bool BatteryNotify::PublishChangedEventInner(const BatteryInfo& info) const
{
Want want;
want.SetParam(BatteryInfo::COMMON_EVENT_KEY_PLUGGED_MAX_CURRENT, info.GetPluggedMaxCurrent());
want.SetParam(BatteryInfo::COMMON_EVENT_KEY_PLUGGED_MAX_VOLTAGE, info.GetPluggedMaxVoltage());
want.SetParam(BatteryInfo::COMMON_EVENT_KEY_PLUGGED_NOW_CURRENT, info.GetNowCurrent());
want.SetParam(BatteryInfo::COMMON_EVENT_KEY_CHARGE_COUNTER, info.GetChargeCounter());
want.SetAction(BatteryInfo::COMMON_EVENT_BATTERY_CHANGED_INNER);
CommonEventData data;
data.SetWant(want);
CommonEventPublishInfo publishInfo;
publishInfo.SetOrdered(false);
const std::vector<std::string> permissionVec { "ohos.permission.POWER_OPTIMIZATION" };
publishInfo.SetSubscriberPermissions(permissionVec);
bool isSuccess = true;
isSuccess = CommonEventManager::PublishCommonEvent(data, publishInfo);
if (!isSuccess) {
BATTERY_HILOGE(FEATURE_BATT_INFO, "failed to publish BATTERY_CHANGED_INNER event");
}
return isSuccess;
}
bool BatteryNotify::PublishLowEvent(const BatteryInfo& info) const
{
bool isSuccess = true;
if (info.GetCapacity() > lowCapacity_) {
g_batteryLowOnce = false;
return isSuccess;
}
if (g_batteryLowOnce) {
return isSuccess;
}
Want want;
want.SetAction(CommonEventSupport::COMMON_EVENT_BATTERY_LOW);
CommonEventData data;
data.SetWant(want);
CommonEventPublishInfo publishInfo;
publishInfo.SetOrdered(false);
data.SetCode(info.GetCapacity());
BATTERY_HILOGD(FEATURE_BATT_INFO, "publisher capacity=%{public}d", info.GetCapacity());
isSuccess = CommonEventManager::PublishCommonEvent(data, publishInfo);
if (!isSuccess) {
BATTERY_HILOGE(FEATURE_BATT_INFO, "failed to publish battery_low event");
}
g_batteryLowOnce = true;
return isSuccess;
}
bool BatteryNotify::PublishOkayEvent(const BatteryInfo& info) const
{
bool isSuccess = true;
if (info.GetCapacity() <= lowCapacity_) {
g_batteryOkOnce = false;
return isSuccess;
}
if (g_batteryOkOnce) {
return isSuccess;
}
Want want;
want.SetAction(CommonEventSupport::COMMON_EVENT_BATTERY_OKAY);
CommonEventData data;
data.SetWant(want);
CommonEventPublishInfo publishInfo;
publishInfo.SetOrdered(false);
data.SetCode(info.GetCapacity());
BATTERY_HILOGD(FEATURE_BATT_INFO, "publisher capacity=%{public}d", info.GetCapacity());
isSuccess = CommonEventManager::PublishCommonEvent(data, publishInfo);
if (!isSuccess) {
BATTERY_HILOGD(FEATURE_BATT_INFO, "failed to publish battery_okay event");
}
g_batteryOkOnce = true;
return isSuccess;
}
#ifdef BATTERY_MANAGER_ENABLE_CHARGING_SOUND
namespace {
std::atomic<bool> g_stopping = false;
std::atomic<bool> g_released = true;
constexpr int MAX_PLAY_TIME_MS = 2000;
constexpr int TICK_INTERVAL_MS = 100;
constexpr int US_PER_MS = 1000;
void AntiMemLeak()
{
void* tmpHandle = dlopen("libphonenumber_standard.z.so", RTLD_LAZY | RTLD_NODELETE);
if (!tmpHandle) {
BATTERY_HILOGE(FEATURE_BATT_INFO, "dlopen libphonenumber_standard.z.so failed");
} else {
dlclose(tmpHandle);
}
}
void StartChargingSoundFunc()
{
#ifdef CONFIG_USE_JEMALLOC_DFX_INTF
OHOS::PowerMgr::MemoryGuard guard;
#endif
if (!g_service || !g_service->IsBootCompleted()) {
return;
}
bool expected = true;
bool ret = g_released.compare_exchange_strong(expected, false);
if (!ret) {
BATTERY_HILOGE(FEATURE_BATT_INFO, "charging sound not released");
return;
}
AntiMemLeak();
void* handle = dlopen("libcharging_sound.z.so", RTLD_NOLOAD);
if (!handle) {
BATTERY_HILOGI(FEATURE_BATT_INFO, "libcharging_sound not loaded");
handle = dlopen("libcharging_sound.z.so", RTLD_LAZY);
}
if (!handle) {
BATTERY_HILOGE(FEATURE_BATT_INFO, "dlopen libcharging_sound failed: ret=%{public}s", dlerror());
g_released.store(true);
return;
}
auto ChargingSoundStart = reinterpret_cast<bool(*)(void)>(dlsym(handle, "ChargingSoundStart"));
auto IsPlaying = reinterpret_cast<bool (*)(void)>(dlsym(handle, "IsPlaying"));
auto ChargingSoundRelease = reinterpret_cast<bool (*)(void)>(dlsym(handle, "ChargingSoundRelease"));
if (!IsPlaying || !ChargingSoundStart || !ChargingSoundRelease) {
BATTERY_HILOGE(FEATURE_BATT_INFO, "dlsym failed");
dlclose(handle);
g_released.store(true);
return;
}
g_stopping.store(false);
ffrt::submit([ChargingSoundStart, IsPlaying, ChargingSoundRelease, handle]() {
#ifdef CONFIG_USE_JEMALLOC_DFX_INTF
OHOS::PowerMgr::MemoryGuard guard;
#endif
if (!ChargingSoundStart()) {
BATTERY_HILOGE(FEATURE_BATT_INFO, "ChargingSoundStart failed");
g_released.store(true);
return;
}
for (int timePassed = 0; timePassed < MAX_PLAY_TIME_MS; timePassed += TICK_INTERVAL_MS) {
if (g_stopping.load()) {
break;
}
if (!IsPlaying()) {
break;
}
usleep(TICK_INTERVAL_MS * US_PER_MS);
}
if (!ChargingSoundRelease()) {
BATTERY_HILOGE(FEATURE_BATT_INFO, "ChargingSoundRelease failed");
g_released.store(true);
return;
}
dlclose(handle);
g_released.store(true);
});
}
}
#endif
bool BatteryNotify::PublishPowerConnectedEvent(const BatteryInfo& info) const
{
bool isSuccess = true;
if ((info.GetPluggedType() == BatteryPluggedType::PLUGGED_TYPE_NONE) ||
(info.GetPluggedType() == BatteryPluggedType::PLUGGED_TYPE_BUTT)) {
g_batteryConnectOnce = false;
return isSuccess;
}
if (g_batteryConnectOnce) {
return isSuccess;
}
StartVibrator();
#ifdef BATTERY_MANAGER_ENABLE_CHARGING_SOUND
TriggerChargingSound(true);
#endif
Want want;
want.SetAction(CommonEventSupport::COMMON_EVENT_POWER_CONNECTED);
CommonEventData data;
data.SetWant(want);
CommonEventPublishInfo publishInfo;
publishInfo.SetOrdered(false);
data.SetCode(static_cast<int32_t>(info.GetPluggedType()));
BATTERY_HILOGD(FEATURE_BATT_INFO, "publisher pluggedtype=%{public}u",
static_cast<uint32_t>(info.GetPluggedType()));
isSuccess = CommonEventManager::PublishCommonEvent(data, publishInfo);
if (!isSuccess) {
BATTERY_HILOGE(FEATURE_BATT_INFO, "failed to publish power_connected event");
}
g_batteryConnectOnce = true;
return isSuccess;
}
void BatteryNotify::StartVibrator() const
{
std::shared_ptr<PowerVibrator> vibrator = PowerVibrator::GetInstance();
std::string scene = "start_charge";
vibrator->StartVibrator(scene);
}
#ifdef BATTERY_MANAGER_ENABLE_CHARGING_SOUND
void BatteryNotify::TriggerChargingSound(bool isStart) const
{
sptr<OHOS::ISystemAbilityManager> abilityMgr =
OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
if (abilityMgr == nullptr) {
BATTERY_HILOGE(FEATURE_BATT_INFO, "Failed to get ISystemAbilityManager");
return;
}
sptr<IRemoteObject> remoteObject = abilityMgr->CheckSystemAbility(ABILITY_MGR_SERVICE_ID);
if (remoteObject == nullptr) {
BATTERY_HILOGE(FEATURE_BATT_INFO, "Failed to get ability manager service");
return;
}
sptr<AppExecFwk::IAbilityManager> amsProxy = iface_cast<AppExecFwk::IAbilityManager>(remoteObject);
if (amsProxy == nullptr || !amsProxy->AsObject()) {
BATTERY_HILOGE(FEATURE_BATT_INFO, "Failed to get ability manager proxy");
return;
}
AAFwk::Want want;
want.SetElementName("com.ohos.powerdialog", "ChargeSoundPlayerExtension");
if (isStart) {
std::string audioPath = GetChargingSoundPath();
want.SetParam("audioPath", audioPath);
ErrCode ret = amsProxy->StartExtensionAbility(want, nullptr);
BATTERY_HILOGI(FEATURE_BATT_INFO, "StartExtensionAbility, ret=%{public}d", ret);
} else {
ErrCode ret = amsProxy->StopExtensionAbility(want, nullptr);
BATTERY_HILOGI(FEATURE_BATT_INFO, "StopExtensionAbility, ret=%{public}d", ret);
}
}
std::string BatteryNotify::GetChargingSoundPath() const
{
const int32_t MAX_AUDIO_PATH_LEN = 1024;
char buf[MAX_AUDIO_PATH_LEN] = {0};
std::string audioPath = "/vendor/etc/battery/PowerConnected.ogg";
char* path = GetOneCfgFile("resource/media/audio/ui/PowerConnected.ogg", buf, MAX_AUDIO_PATH_LEN);
if (path != nullptr && *path != '\0') {
return std::string{path};
}
BATTERY_HILOGW(FEATURE_BATT_INFO, "GetOneCfgFile failed, using default audio path");
return audioPath;
}
#endif
bool BatteryNotify::PublishPowerDisconnectedEvent(const BatteryInfo& info) const
{
bool isSuccess = true;
if ((info.GetPluggedType() != BatteryPluggedType::PLUGGED_TYPE_NONE) &&
(info.GetPluggedType() != BatteryPluggedType::PLUGGED_TYPE_BUTT)) {
g_batteryDisconnectOnce = false;
return isSuccess;
}
if (g_batteryDisconnectOnce) {
return isSuccess;
}
#ifdef BATTERY_MANAGER_ENABLE_CHARGING_SOUND
TriggerChargingSound(false);
#endif
Want want;
want.SetAction(CommonEventSupport::COMMON_EVENT_POWER_DISCONNECTED);
CommonEventData data;
data.SetWant(want);
CommonEventPublishInfo publishInfo;
publishInfo.SetOrdered(false);
data.SetCode(static_cast<int32_t>(info.GetPluggedType()));
BATTERY_HILOGD(FEATURE_BATT_INFO, "publisher pluggedtype=%{public}u",
static_cast<uint32_t>(info.GetPluggedType()));
isSuccess = CommonEventManager::PublishCommonEvent(data, publishInfo);
if (!isSuccess) {
BATTERY_HILOGD(FEATURE_BATT_INFO, "failed to publish power_disconnected event");
}
g_batteryDisconnectOnce = true;
return isSuccess;
}
bool BatteryNotify::PublishChargingEvent(const BatteryInfo& info) const
{
bool isSuccess = true;
if ((info.GetChargeState() != BatteryChargeState::CHARGE_STATE_ENABLE) &&
(info.GetChargeState() != BatteryChargeState::CHARGE_STATE_FULL)) {
g_batteryChargingOnce = false;
return isSuccess;
}
if (g_batteryChargingOnce) {
return isSuccess;
}
Want want;
want.SetAction(CommonEventSupport::COMMON_EVENT_CHARGING);
CommonEventData data;
data.SetWant(want);
CommonEventPublishInfo publishInfo;
publishInfo.SetOrdered(false);
data.SetCode(static_cast<int32_t>(info.GetChargeState()));
BATTERY_HILOGD(FEATURE_BATT_INFO, "publisher chargeState=%{public}u",
static_cast<uint32_t>(info.GetChargeState()));
isSuccess = CommonEventManager::PublishCommonEvent(data, publishInfo);
if (!isSuccess) {
BATTERY_HILOGD(FEATURE_BATT_INFO, "failed to publish battery charing event");
}
g_batteryChargingOnce = true;
return isSuccess;
}
bool BatteryNotify::PublishDischargingEvent(const BatteryInfo& info) const
{
bool isSuccess = true;
if ((info.GetChargeState() == BatteryChargeState::CHARGE_STATE_ENABLE) ||
(info.GetChargeState() == BatteryChargeState::CHARGE_STATE_FULL)) {
g_batteryDischargingOnce = false;
return isSuccess;
}
if (g_batteryDischargingOnce) {
return isSuccess;
}
Want want;
want.SetAction(CommonEventSupport::COMMON_EVENT_DISCHARGING);
CommonEventData data;
data.SetWant(want);
CommonEventPublishInfo publishInfo;
publishInfo.SetOrdered(false);
data.SetCode(static_cast<int32_t>(info.GetChargeState()));
BATTERY_HILOGD(FEATURE_BATT_INFO, "publisher chargeState=%{public}u",
static_cast<uint32_t>(info.GetChargeState()));
isSuccess = CommonEventManager::PublishCommonEvent(data, publishInfo);
if (!isSuccess) {
BATTERY_HILOGD(FEATURE_BATT_INFO, "failed to publish battery charing event");
}
g_batteryDischargingOnce = true;
return isSuccess;
}
bool BatteryNotify::PublishCustomEvent(const BatteryInfo& info, const std::string& commonEventName) const
{
UEVENT_CHECK_INFO ueventCheckInfo = {
.UeventName = info.GetUevent(),
.checkResult = true
};
int ret = HookMgrExecute(GetBatteryHookMgr(), static_cast<int32_t>(BatteryHookStage::BATTERY_UEVENT_CHECK),
(void*)&ueventCheckInfo, nullptr);
if (ret == 0 && !ueventCheckInfo.checkResult) {
BATTERY_HILOGW(FEATURE_BATT_INFO, "PublishCustomEvent fail, uevent=%{public}s, checkResult=%{public}d",
ueventCheckInfo.UeventName.c_str(), ueventCheckInfo.checkResult);
return false;
}
Want want;
want.SetParam(BatteryInfo::COMMON_EVENT_KEY_UEVENT, info.GetUevent());
want.SetAction(commonEventName);
CommonEventData data;
data.SetWant(want);
CommonEventPublishInfo publishInfo;
publishInfo.SetOrdered(false);
const std::vector<std::string> permissionVec { "ohos.permission.POWER_OPTIMIZATION" };
publishInfo.SetSubscriberPermissions(permissionVec);
bool isSuccess = CommonEventManager::PublishCommonEvent(data, publishInfo);
if (!isSuccess) {
BATTERY_HILOGD(FEATURE_BATT_INFO, "failed to publish battery custom event");
}
return isSuccess;
}
bool BatteryNotify::HandleNotification(const std::string& ueventName) const
{
#ifdef BATTERY_SUPPORT_NOTIFICATION
std::unordered_map<std::string, std::vector<BatteryConfig::PopupConf>> popupCfg =
BatteryConfig::GetInstance().GetPopupConf();
auto iter = popupCfg.find(ueventName);
if (iter == popupCfg.end()) {
BATTERY_HILOGW(COMP_SVC, "HandleNotification not found conf: %{public}s", ueventName.c_str());
return false;
}
typedef void(*HandleNotificationFunc)(const std::string&, int32_t,
const std::unordered_map<std::string, BatteryConfig::NotificationConf>&);
void* handler = dlopen("libbattery_notification.z.so", RTLD_LAZY | RTLD_NODELETE);
if (handler == nullptr) {
BATTERY_HILOGE(FEATURE_BATT_INFO, "dlopen HandleNotificationFunc failed, reason : %{public}s", dlerror());
return false;
}
HandleNotificationFunc HandleNotification =
reinterpret_cast<HandleNotificationFunc>(dlsym(handler, "HandleNotification"));
if (HandleNotification == nullptr) {
BATTERY_HILOGE(FEATURE_BATT_INFO, "HandleNotificationFunc is null, reason : %{public}s", dlerror());
dlclose(handler);
handler = nullptr;
return false;
}
auto nConfMap = BatteryConfig::GetInstance().GetNotificationConf();
for (auto& item : iter->second) {
HandleNotification(item.name, item.action, nConfMap);
BATTERY_HILOGI(COMP_SVC, "popupName=%{public}s, popupAction=%{public}d", item.name.c_str(), item.action);
}
dlclose(handler);
handler = nullptr;
#endif
return true;
}
}
}