1 /*
2  * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "battery_notify.h"
17 #include <regex>
18 
19 #ifdef BATTERY_MANAGER_ENABLE_CHARGING_SOUND
20 #include "charging_sound.h"
21 #endif
22 #include "common_event_data.h"
23 #include "common_event_manager.h"
24 #include "common_event_publish_info.h"
25 #include "common_event_support.h"
26 #include "errors.h"
27 #include "hisysevent.h"
28 #include "if_system_ability_manager.h"
29 #include "iservice_registry.h"
30 #include "string_ex.h"
31 #include "system_ability_definition.h"
32 
33 #include "battery_config.h"
34 #include "battery_log.h"
35 #include "battery_service.h"
36 #include "power_vibrator.h"
37 #include "power_mgr_client.h"
38 
39 using namespace OHOS::AAFwk;
40 using namespace OHOS::EventFwk;
41 using namespace OHOS::HiviewDFX;
42 
43 namespace OHOS {
44 namespace PowerMgr {
45 bool g_batteryLowOnce = false;
46 bool g_batteryOkOnce = false;
47 bool g_batteryConnectOnce = false;
48 bool g_batteryDisconnectOnce = false;
49 bool g_batteryChargingOnce = false;
50 bool g_batteryDischargingOnce = false;
51 bool g_commonEventInitSuccess = false;
52 OHOS::PowerMgr::BatteryCapacityLevel g_lastCapacityLevel = OHOS::PowerMgr::BatteryCapacityLevel::LEVEL_NONE;
53 const std::string POWER_SUPPLY = "SUBSYSTEM=power_supply";
54 const std::string SHUTDOWN = "shutdown";
55 const std::string REBOOT = "reboot";
56 const std::string SEND_COMMONEVENT = "sendcommonevent";
57 const std::string SEND_CUSTOMEVENT = "sendcustomevent";
58 const std::string BATTERY_CUSTOM_EVENT = "usual.event.battery.custom";
59 const std::string BATTERY_CUSTOM_EVENT_PREFIX = "usual.event.battery";
60 sptr<BatteryService> g_service = DelayedSpSingleton<BatteryService>::GetInstance();
61 
BatteryNotify()62 BatteryNotify::BatteryNotify()
63 {
64     const int32_t DEFAULT_LOW_CAPACITY = 20;
65     lowCapacity_ = BatteryConfig::GetInstance().GetInt("soc.low", DEFAULT_LOW_CAPACITY);
66     BATTERY_HILOGI(COMP_SVC, "Low broadcast power=%{public}d", lowCapacity_);
67 }
68 
PublishEvents(BatteryInfo & info)69 int32_t BatteryNotify::PublishEvents(BatteryInfo& info)
70 {
71     if (!g_commonEventInitSuccess) {
72         if (!IsCommonEventServiceAbilityExist()) {
73             return ERR_NO_INIT;
74         }
75     }
76     if (info.GetUevent() != POWER_SUPPLY && info.GetUevent() != "") {
77         HandleUevent(info);
78         return ERR_OK;
79     }
80 
81     bool isAllSuccess = true;
82     bool ret = PublishChangedEvent(info);
83     isAllSuccess &= ret;
84     ret = PublishChangedEventInner(info);
85     isAllSuccess &= ret;
86     ret = PublishLowEvent(info);
87     isAllSuccess &= ret;
88     ret = PublishOkayEvent(info);
89     isAllSuccess &= ret;
90     ret = PublishPowerConnectedEvent(info);
91     isAllSuccess &= ret;
92     ret = PublishPowerDisconnectedEvent(info);
93     isAllSuccess &= ret;
94     ret = PublishChargingEvent(info);
95     isAllSuccess &= ret;
96     ret = PublishDischargingEvent(info);
97     isAllSuccess &= ret;
98     ret = PublishChargeTypeChangedEvent(info);
99     isAllSuccess &= ret;
100 
101     return isAllSuccess ? ERR_OK : ERR_NO_INIT;
102 }
103 
HandleUevent(BatteryInfo & info)104 void BatteryNotify::HandleUevent(BatteryInfo& info)
105 {
106     std::string uevent = info.GetUevent();
107     auto pos = uevent.rfind('$');
108     if (pos != std::string::npos) {
109         std::string ueventName = uevent.substr(0, pos);
110         std::string ueventAct = uevent.substr(++pos);
111         BATTERY_HILOGI(COMP_SVC, "%{public}s decision %{public}s",
112             ueventName.c_str(), ueventAct.c_str());
113         if (ueventAct == SHUTDOWN) {
114             const std::string reason = "POWEROFF_CHARGE_DISABLE";
115             PowerMgrClient::GetInstance().ShutDownDevice(reason);
116         } else if (ueventAct == REBOOT) {
117             PowerMgrClient::GetInstance().RebootDevice(ueventName);
118         } else if (ueventAct == SEND_COMMONEVENT) {
119             info.SetUevent(ueventName);
120             PublishChangedEvent(info);
121         } else if (ueventAct == SEND_CUSTOMEVENT) {
122             info.SetUevent(ueventName);
123             PublishCustomEvent(info, BATTERY_CUSTOM_EVENT);
124         } else if (ueventAct.compare(0, BATTERY_CUSTOM_EVENT_PREFIX.size(), BATTERY_CUSTOM_EVENT_PREFIX) == 0) {
125             info.SetUevent(ueventName);
126             PublishCustomEvent(info, ueventAct);
127         } else {
128             BATTERY_HILOGE(COMP_SVC, "undefine uevent act %{public}s", ueventAct.c_str());
129         }
130     }
131     BATTERY_HILOGI(COMP_SVC, "handle uevent info %{public}s", uevent.c_str());
132 }
133 
PublishChargeTypeChangedEvent(const BatteryInfo & info)134 bool BatteryNotify::PublishChargeTypeChangedEvent(const BatteryInfo& info)
135 {
136     ChargeType chargeType = info.GetChargeType();
137     bool isSuccess = true;
138     if (batteryInfoChargeType_ == chargeType) {
139         BATTERY_HILOGD(COMP_SVC, "No need to send chargetype event");
140         return isSuccess;
141     }
142     batteryInfoChargeType_ = chargeType;
143     Want want;
144     want.SetAction(CommonEventSupport::COMMON_EVENT_CHARGE_TYPE_CHANGED);
145     CommonEventData data;
146     data.SetWant(want);
147     CommonEventPublishInfo publishInfo;
148     publishInfo.SetOrdered(false);
149 
150     data.SetCode(static_cast<int32_t>(chargeType));
151     BATTERY_HILOGD(COMP_SVC, "publisher chargeType=%{public}d", chargeType);
152     isSuccess = CommonEventManager::PublishCommonEvent(data, publishInfo);
153     if (!isSuccess) {
154         BATTERY_HILOGD(COMP_SVC, "failed to publish battery charge type event");
155     }
156 
157     return isSuccess;
158 }
159 
IsCommonEventServiceAbilityExist() const160 bool BatteryNotify::IsCommonEventServiceAbilityExist() const
161 {
162     sptr<ISystemAbilityManager> sysMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
163     if (!sysMgr) {
164         BATTERY_HILOGE(COMP_SVC,
165             "IsCommonEventServiceAbilityExist Get ISystemAbilityManager failed, no SystemAbilityManager");
166         return false;
167     }
168     sptr<IRemoteObject> remote = sysMgr->CheckSystemAbility(COMMON_EVENT_SERVICE_ID);
169     if (!remote) {
170         BATTERY_HILOGE(COMP_SVC, "No CesServiceAbility");
171         return false;
172     }
173 
174     if (!g_commonEventInitSuccess) {
175         BATTERY_HILOGI(COMP_SVC, "common event service ability init success");
176         g_commonEventInitSuccess = true;
177     }
178 
179     return true;
180 }
181 
PublishChangedEvent(const BatteryInfo & info)182 bool BatteryNotify::PublishChangedEvent(const BatteryInfo& info)
183 {
184     Want want;
185     int32_t capacity = info.GetCapacity();
186     int32_t pluggedType = static_cast<int32_t>(info.GetPluggedType());
187     int32_t temperature = info.GetTemperature();
188     int32_t healthState = static_cast<int32_t>(info.GetHealthState());
189     want.SetParam(BatteryInfo::COMMON_EVENT_KEY_CAPACITY, capacity);
190     want.SetParam(BatteryInfo::COMMON_EVENT_KEY_VOLTAGE, info.GetVoltage());
191     want.SetParam(BatteryInfo::COMMON_EVENT_KEY_TEMPERATURE, temperature);
192     want.SetParam(BatteryInfo::COMMON_EVENT_KEY_HEALTH_STATE, healthState);
193     want.SetParam(BatteryInfo::COMMON_EVENT_KEY_PLUGGED_TYPE, pluggedType);
194     want.SetParam(BatteryInfo::COMMON_EVENT_KEY_CHARGE_STATE, static_cast<int32_t>(info.GetChargeState()));
195     want.SetParam(BatteryInfo::COMMON_EVENT_KEY_PRESENT, info.IsPresent());
196     want.SetParam(BatteryInfo::COMMON_EVENT_KEY_TECHNOLOGY, info.GetTechnology());
197     want.SetParam(BatteryInfo::COMMON_EVENT_KEY_UEVENT, info.GetUevent());
198 
199     auto capacityLevel = g_service->GetCapacityLevel();
200     if (capacityLevel != g_lastCapacityLevel) {
201         want.SetParam(BatteryInfo::COMMON_EVENT_KEY_CAPACITY_LEVEL, static_cast<int32_t>(capacityLevel));
202         g_lastCapacityLevel = capacityLevel;
203     }
204 
205     want.SetAction(CommonEventSupport::COMMON_EVENT_BATTERY_CHANGED);
206     CommonEventData data;
207     data.SetWant(want);
208     CommonEventPublishInfo publishInfo;
209     publishInfo.SetOrdered(false);
210     if (capacity != lastCapacity_ || pluggedType != lastPluggedType_ ||
211         temperature != lastTemperature_ || healthState != lastHealthState_) {
212         HiSysEventWrite(HiSysEvent::Domain::BATTERY, "CHANGED", HiSysEvent::EventType::STATISTIC,
213             "LEVEL", capacity, "CHARGER", pluggedType, "VOLTAGE", info.GetVoltage(),
214             "TEMPERATURE", temperature, "HEALTH", healthState, "CURRENT", info.GetNowCurrent());
215         lastCapacity_ = capacity;
216         lastPluggedType_ = pluggedType;
217         lastTemperature_ = temperature;
218         lastHealthState_ = healthState;
219     }
220     bool isSuccess = CommonEventManager::PublishCommonEvent(data, publishInfo);
221     if (!isSuccess) {
222         BATTERY_HILOGE(FEATURE_BATT_INFO, "failed to publish BATTERY_CHANGED event");
223     }
224     return isSuccess;
225 }
226 
PublishChangedEventInner(const BatteryInfo & info) const227 bool BatteryNotify::PublishChangedEventInner(const BatteryInfo& info) const
228 {
229     Want want;
230     want.SetParam(BatteryInfo::COMMON_EVENT_KEY_PLUGGED_MAX_CURRENT, info.GetPluggedMaxCurrent());
231     want.SetParam(BatteryInfo::COMMON_EVENT_KEY_PLUGGED_MAX_VOLTAGE, info.GetPluggedMaxVoltage());
232     want.SetParam(BatteryInfo::COMMON_EVENT_KEY_PLUGGED_NOW_CURRENT, info.GetNowCurrent());
233     want.SetParam(BatteryInfo::COMMON_EVENT_KEY_CHARGE_COUNTER, info.GetChargeCounter());
234 
235     want.SetAction(BatteryInfo::COMMON_EVENT_BATTERY_CHANGED_INNER);
236     CommonEventData data;
237     data.SetWant(want);
238     CommonEventPublishInfo publishInfo;
239     publishInfo.SetOrdered(false);
240     const std::vector<std::string> permissionVec { "ohos.permission.POWER_OPTIMIZATION" };
241     publishInfo.SetSubscriberPermissions(permissionVec);
242 
243     bool isSuccess = true;
244     isSuccess = CommonEventManager::PublishCommonEvent(data, publishInfo);
245     if (!isSuccess) {
246         BATTERY_HILOGE(FEATURE_BATT_INFO, "failed to publish BATTERY_CHANGED_INNER event");
247     }
248     return isSuccess;
249 }
250 
PublishLowEvent(const BatteryInfo & info) const251 bool BatteryNotify::PublishLowEvent(const BatteryInfo& info) const
252 {
253     bool isSuccess = true;
254 
255     if (info.GetCapacity() > lowCapacity_) {
256         g_batteryLowOnce = false;
257         return isSuccess;
258     }
259 
260     if (g_batteryLowOnce) {
261         return isSuccess;
262     }
263 
264     Want want;
265     want.SetAction(CommonEventSupport::COMMON_EVENT_BATTERY_LOW);
266     CommonEventData data;
267     data.SetWant(want);
268     CommonEventPublishInfo publishInfo;
269     publishInfo.SetOrdered(false);
270     data.SetCode(info.GetCapacity());
271     BATTERY_HILOGD(FEATURE_BATT_INFO, "publisher capacity=%{public}d", info.GetCapacity());
272     isSuccess = CommonEventManager::PublishCommonEvent(data, publishInfo);
273     if (!isSuccess) {
274         BATTERY_HILOGE(FEATURE_BATT_INFO, "failed to publish battery_low event");
275     }
276     g_batteryLowOnce = true;
277     return isSuccess;
278 }
279 
PublishOkayEvent(const BatteryInfo & info) const280 bool BatteryNotify::PublishOkayEvent(const BatteryInfo& info) const
281 {
282     bool isSuccess = true;
283 
284     if (info.GetCapacity() <= lowCapacity_) {
285         g_batteryOkOnce = false;
286         return isSuccess;
287     }
288 
289     if (g_batteryOkOnce) {
290         return isSuccess;
291     }
292 
293     Want want;
294     want.SetAction(CommonEventSupport::COMMON_EVENT_BATTERY_OKAY);
295     CommonEventData data;
296     data.SetWant(want);
297     CommonEventPublishInfo publishInfo;
298     publishInfo.SetOrdered(false);
299     data.SetCode(info.GetCapacity());
300     BATTERY_HILOGD(FEATURE_BATT_INFO, "publisher capacity=%{public}d", info.GetCapacity());
301     isSuccess = CommonEventManager::PublishCommonEvent(data, publishInfo);
302     if (!isSuccess) {
303         BATTERY_HILOGD(FEATURE_BATT_INFO, "failed to publish battery_okay event");
304     }
305     g_batteryOkOnce = true;
306     return isSuccess;
307 }
308 
PublishPowerConnectedEvent(const BatteryInfo & info) const309 bool BatteryNotify::PublishPowerConnectedEvent(const BatteryInfo& info) const
310 {
311     bool isSuccess = true;
312 
313     if ((info.GetPluggedType() == BatteryPluggedType::PLUGGED_TYPE_NONE) ||
314         (info.GetPluggedType() == BatteryPluggedType::PLUGGED_TYPE_BUTT)) {
315         g_batteryConnectOnce = false;
316         return isSuccess;
317     }
318 
319     if (g_batteryConnectOnce) {
320         return isSuccess;
321     }
322     StartVibrator();
323 #ifdef BATTERY_MANAGER_ENABLE_CHARGING_SOUND
324     if (g_service && g_service->IsBootCompleted()) {
325         ChargingSound::GetInstance().Start();
326     }
327 #endif
328     Want want;
329     want.SetAction(CommonEventSupport::COMMON_EVENT_POWER_CONNECTED);
330     CommonEventData data;
331     data.SetWant(want);
332     CommonEventPublishInfo publishInfo;
333     publishInfo.SetOrdered(false);
334     data.SetCode(static_cast<int32_t>(info.GetPluggedType()));
335     BATTERY_HILOGD(FEATURE_BATT_INFO, "publisher pluggedtype=%{public}u",
336         static_cast<uint32_t>(info.GetPluggedType()));
337     isSuccess = CommonEventManager::PublishCommonEvent(data, publishInfo);
338     if (!isSuccess) {
339         BATTERY_HILOGE(FEATURE_BATT_INFO, "failed to publish power_connected event");
340     }
341 
342     g_batteryConnectOnce = true;
343     return isSuccess;
344 }
345 
StartVibrator() const346 void BatteryNotify::StartVibrator() const
347 {
348     std::shared_ptr<PowerVibrator> vibrator = PowerVibrator::GetInstance();
349     std::string scene = "start_charge";
350     vibrator->StartVibrator(scene);
351 }
352 
PublishPowerDisconnectedEvent(const BatteryInfo & info) const353 bool BatteryNotify::PublishPowerDisconnectedEvent(const BatteryInfo& info) const
354 {
355     bool isSuccess = true;
356 
357     if ((info.GetPluggedType() != BatteryPluggedType::PLUGGED_TYPE_NONE) &&
358         (info.GetPluggedType() != BatteryPluggedType::PLUGGED_TYPE_BUTT)) {
359         g_batteryDisconnectOnce = false;
360         return isSuccess;
361     }
362 
363     if (g_batteryDisconnectOnce) {
364         return isSuccess;
365     }
366 #ifdef BATTERY_MANAGER_ENABLE_CHARGING_SOUND
367     if (g_service && g_service->IsBootCompleted()) {
368         ChargingSound::GetInstance().Stop();
369     }
370 #endif
371     Want want;
372     want.SetAction(CommonEventSupport::COMMON_EVENT_POWER_DISCONNECTED);
373     CommonEventData data;
374     data.SetWant(want);
375     CommonEventPublishInfo publishInfo;
376     publishInfo.SetOrdered(false);
377     data.SetCode(static_cast<int32_t>(info.GetPluggedType()));
378     BATTERY_HILOGD(FEATURE_BATT_INFO, "publisher pluggedtype=%{public}u",
379         static_cast<uint32_t>(info.GetPluggedType()));
380     isSuccess = CommonEventManager::PublishCommonEvent(data, publishInfo);
381     if (!isSuccess) {
382         BATTERY_HILOGD(FEATURE_BATT_INFO, "failed to publish power_disconnected event");
383     }
384 
385     g_batteryDisconnectOnce = true;
386     return isSuccess;
387 }
388 
PublishChargingEvent(const BatteryInfo & info) const389 bool BatteryNotify::PublishChargingEvent(const BatteryInfo& info) const
390 {
391     bool isSuccess = true;
392 
393     if ((info.GetChargeState() != BatteryChargeState::CHARGE_STATE_ENABLE) &&
394         (info.GetChargeState() != BatteryChargeState::CHARGE_STATE_FULL)) {
395         g_batteryChargingOnce = false;
396         return isSuccess;
397     }
398 
399     if (g_batteryChargingOnce) {
400         return isSuccess;
401     }
402 
403     Want want;
404     want.SetAction(CommonEventSupport::COMMON_EVENT_CHARGING);
405     CommonEventData data;
406     data.SetWant(want);
407     CommonEventPublishInfo publishInfo;
408     publishInfo.SetOrdered(false);
409     data.SetCode(static_cast<int32_t>(info.GetChargeState()));
410     BATTERY_HILOGD(FEATURE_BATT_INFO, "publisher chargeState=%{public}u",
411         static_cast<uint32_t>(info.GetChargeState()));
412     isSuccess = CommonEventManager::PublishCommonEvent(data, publishInfo);
413     if (!isSuccess) {
414         BATTERY_HILOGD(FEATURE_BATT_INFO, "failed to publish battery charing event");
415     }
416 
417     g_batteryChargingOnce = true;
418     return isSuccess;
419 }
420 
PublishDischargingEvent(const BatteryInfo & info) const421 bool BatteryNotify::PublishDischargingEvent(const BatteryInfo& info) const
422 {
423     bool isSuccess = true;
424 
425     if ((info.GetChargeState() == BatteryChargeState::CHARGE_STATE_ENABLE) ||
426         (info.GetChargeState() == BatteryChargeState::CHARGE_STATE_FULL)) {
427         g_batteryDischargingOnce = false;
428         return isSuccess;
429     }
430 
431     if (g_batteryDischargingOnce) {
432         return isSuccess;
433     }
434 
435     Want want;
436     want.SetAction(CommonEventSupport::COMMON_EVENT_DISCHARGING);
437     CommonEventData data;
438     data.SetWant(want);
439     CommonEventPublishInfo publishInfo;
440     publishInfo.SetOrdered(false);
441     data.SetCode(static_cast<int32_t>(info.GetChargeState()));
442     BATTERY_HILOGD(FEATURE_BATT_INFO, "publisher chargeState=%{public}u",
443         static_cast<uint32_t>(info.GetChargeState()));
444     isSuccess = CommonEventManager::PublishCommonEvent(data, publishInfo);
445     if (!isSuccess) {
446         BATTERY_HILOGD(FEATURE_BATT_INFO, "failed to publish battery charing event");
447     }
448 
449     g_batteryDischargingOnce = true;
450     return isSuccess;
451 }
452 
PublishCustomEvent(const BatteryInfo & info,const std::string & commonEventName) const453 bool BatteryNotify::PublishCustomEvent(const BatteryInfo& info, const std::string& commonEventName) const
454 {
455     Want want;
456     want.SetParam(BatteryInfo::COMMON_EVENT_KEY_UEVENT, info.GetUevent());
457     want.SetAction(commonEventName);
458     CommonEventData data;
459     data.SetWant(want);
460     CommonEventPublishInfo publishInfo;
461     publishInfo.SetOrdered(false);
462     const std::vector<std::string> permissionVec { "ohos.permission.POWER_OPTIMIZATION" };
463     publishInfo.SetSubscriberPermissions(permissionVec);
464 
465     bool isSuccess = CommonEventManager::PublishCommonEvent(data, publishInfo);
466     if (!isSuccess) {
467         BATTERY_HILOGD(FEATURE_BATT_INFO, "failed to publish battery custom event");
468     }
469     return isSuccess;
470 }
471 } // namespace PowerMgr
472 } // namespace OHOS
473