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 #include "common_event_data.h"
20 #include "common_event_manager.h"
21 #include "common_event_publish_info.h"
22 #include "common_event_support.h"
23 #include "errors.h"
24 #ifdef HAS_HIVIEWDFX_HISYSEVENT_PART
25 #include "hisysevent.h"
26 #endif
27 #include "if_system_ability_manager.h"
28 #include "iservice_registry.h"
29 #include "string_ex.h"
30 #include "system_ability_definition.h"
31 
32 #include "battery_config.h"
33 #include "battery_log.h"
34 #include "battery_service.h"
35 #include "power_vibrator.h"
36 #include "power_mgr_client.h"
37 
38 using namespace OHOS::AAFwk;
39 using namespace OHOS::EventFwk;
40 #ifdef HAS_HIVIEWDFX_HISYSEVENT_PART
41 using namespace OHOS::HiviewDFX;
42 #endif
43 
44 namespace OHOS {
45 namespace PowerMgr {
46 bool g_batteryLowOnce = false;
47 bool g_batteryOkOnce = false;
48 bool g_batteryConnectOnce = false;
49 bool g_batteryDisconnectOnce = false;
50 bool g_batteryChargingOnce = false;
51 bool g_batteryDischargingOnce = false;
52 bool g_commonEventInitSuccess = false;
53 OHOS::PowerMgr::BatteryCapacityLevel g_lastCapacityLevel = OHOS::PowerMgr::BatteryCapacityLevel::LEVEL_NONE;
54 const std::string POWER_SUPPLY = "SUBSYSTEM=power_supply";
55 const std::string SHUTDOWN = "shutdown";
56 const std::string REBOOT = "reboot";
57 const std::string SEND_COMMONEVENT = "sendcommonevent";
58 const std::string SEND_CUSTOMEVENT = "sendcustomevent";
59 const std::string BATTERY_CUSTOM_EVENT_PREFIX = "usual.event.";
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.compare(0, BATTERY_CUSTOM_EVENT_PREFIX.size(), BATTERY_CUSTOM_EVENT_PREFIX) == 0) {
122             info.SetUevent(ueventName);
123             PublishCustomEvent(info, ueventAct);
124         } else {
125             BATTERY_HILOGE(COMP_SVC, "undefine uevent act %{public}s", ueventAct.c_str());
126         }
127     }
128     BATTERY_HILOGI(COMP_SVC, "handle uevent info %{public}s", uevent.c_str());
129 }
130 
PublishChargeTypeChangedEvent(const BatteryInfo& info)131 bool BatteryNotify::PublishChargeTypeChangedEvent(const BatteryInfo& info)
132 {
133     ChargeType chargeType = info.GetChargeType();
134     bool isSuccess = true;
135     if (batteryInfoChargeType_ == chargeType) {
136         BATTERY_HILOGD(COMP_SVC, "No need to send chargetype event");
137         return isSuccess;
138     }
139     batteryInfoChargeType_ = chargeType;
140     Want want;
141     want.SetAction(CommonEventSupport::COMMON_EVENT_CHARGE_TYPE_CHANGED);
142     CommonEventData data;
143     data.SetWant(want);
144     CommonEventPublishInfo publishInfo;
145     publishInfo.SetOrdered(false);
146 
147     data.SetCode(static_cast<int32_t>(chargeType));
148     BATTERY_HILOGD(COMP_SVC, "publisher chargeType=%{public}d", chargeType);
149     isSuccess = CommonEventManager::PublishCommonEvent(data, publishInfo);
150     if (!isSuccess) {
151         BATTERY_HILOGD(COMP_SVC, "failed to publish battery charge type event");
152     }
153 
154     return isSuccess;
155 }
156 
IsCommonEventServiceAbilityExist() const157 bool BatteryNotify::IsCommonEventServiceAbilityExist() const
158 {
159     sptr<ISystemAbilityManager> sysMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
160     if (!sysMgr) {
161         BATTERY_HILOGE(COMP_SVC,
162             "IsCommonEventServiceAbilityExist Get ISystemAbilityManager failed, no SystemAbilityManager");
163         return false;
164     }
165     sptr<IRemoteObject> remote = sysMgr->CheckSystemAbility(COMMON_EVENT_SERVICE_ID);
166     if (!remote) {
167         BATTERY_HILOGE(COMP_SVC, "No CesServiceAbility");
168         return false;
169     }
170 
171     if (!g_commonEventInitSuccess) {
172         BATTERY_HILOGI(COMP_SVC, "common event service ability init success");
173         g_commonEventInitSuccess = true;
174     }
175 
176     return true;
177 }
178 
PublishChangedEvent(const BatteryInfo& info)179 bool BatteryNotify::PublishChangedEvent(const BatteryInfo& info)
180 {
181     Want want;
182     int32_t capacity = info.GetCapacity();
183     int32_t pluggedType = static_cast<int32_t>(info.GetPluggedType());
184     int32_t temperature = info.GetTemperature();
185     int32_t healthState = static_cast<int32_t>(info.GetHealthState());
186     want.SetParam(BatteryInfo::COMMON_EVENT_KEY_CAPACITY, capacity);
187     want.SetParam(BatteryInfo::COMMON_EVENT_KEY_VOLTAGE, info.GetVoltage());
188     want.SetParam(BatteryInfo::COMMON_EVENT_KEY_TEMPERATURE, temperature);
189     want.SetParam(BatteryInfo::COMMON_EVENT_KEY_HEALTH_STATE, healthState);
190     want.SetParam(BatteryInfo::COMMON_EVENT_KEY_PLUGGED_TYPE, pluggedType);
191     want.SetParam(BatteryInfo::COMMON_EVENT_KEY_CHARGE_STATE, static_cast<int32_t>(info.GetChargeState()));
192     want.SetParam(BatteryInfo::COMMON_EVENT_KEY_PRESENT, info.IsPresent());
193     want.SetParam(BatteryInfo::COMMON_EVENT_KEY_TECHNOLOGY, info.GetTechnology());
194     want.SetParam(BatteryInfo::COMMON_EVENT_KEY_UEVENT, info.GetUevent());
195 
196     auto capacityLevel = g_service->GetCapacityLevel();
197     if (capacityLevel != g_lastCapacityLevel) {
198         want.SetParam(BatteryInfo::COMMON_EVENT_KEY_CAPACITY_LEVEL, static_cast<int32_t>(capacityLevel));
199         g_lastCapacityLevel = capacityLevel;
200     }
201 
202     want.SetAction(CommonEventSupport::COMMON_EVENT_BATTERY_CHANGED);
203     CommonEventData data;
204     data.SetWant(want);
205     CommonEventPublishInfo publishInfo;
206     publishInfo.SetOrdered(false);
207     if (capacity != lastCapacity_ || pluggedType != lastPluggedType_ ||
208         temperature != lastTemperature_ || healthState != lastHealthState_) {
209 #ifdef HAS_HIVIEWDFX_HISYSEVENT_PART
210         HiSysEventWrite(HiSysEvent::Domain::BATTERY, "CHANGED", HiSysEvent::EventType::STATISTIC,
211             "LEVEL", capacity, "CHARGER", pluggedType, "VOLTAGE", info.GetVoltage(),
212             "TEMPERATURE", temperature, "HEALTH", healthState, "CURRENT", info.GetNowCurrent());
213 #endif
214         lastCapacity_ = capacity;
215         lastPluggedType_ = pluggedType;
216         lastTemperature_ = temperature;
217         lastHealthState_ = healthState;
218     }
219     bool isSuccess = CommonEventManager::PublishCommonEvent(data, publishInfo);
220     if (!isSuccess) {
221         BATTERY_HILOGE(FEATURE_BATT_INFO, "failed to publish BATTERY_CHANGED event");
222     }
223     return isSuccess;
224 }
225 
PublishChangedEventInner(const BatteryInfo& info) const226 bool BatteryNotify::PublishChangedEventInner(const BatteryInfo& info) const
227 {
228     Want want;
229     want.SetParam(BatteryInfo::COMMON_EVENT_KEY_PLUGGED_MAX_CURRENT, info.GetPluggedMaxCurrent());
230     want.SetParam(BatteryInfo::COMMON_EVENT_KEY_PLUGGED_MAX_VOLTAGE, info.GetPluggedMaxVoltage());
231     want.SetParam(BatteryInfo::COMMON_EVENT_KEY_PLUGGED_NOW_CURRENT, info.GetNowCurrent());
232     want.SetParam(BatteryInfo::COMMON_EVENT_KEY_CHARGE_COUNTER, info.GetChargeCounter());
233 
234     want.SetAction(BatteryInfo::COMMON_EVENT_BATTERY_CHANGED_INNER);
235     CommonEventData data;
236     data.SetWant(want);
237     CommonEventPublishInfo publishInfo;
238     publishInfo.SetOrdered(false);
239     const std::vector<std::string> permissionVec { "ohos.permission.POWER_OPTIMIZATION" };
240     publishInfo.SetSubscriberPermissions(permissionVec);
241 
242     bool isSuccess = true;
243     isSuccess = CommonEventManager::PublishCommonEvent(data, publishInfo);
244     if (!isSuccess) {
245         BATTERY_HILOGE(FEATURE_BATT_INFO, "failed to publish BATTERY_CHANGED_INNER event");
246     }
247     return isSuccess;
248 }
249 
PublishLowEvent(const BatteryInfo& info) const250 bool BatteryNotify::PublishLowEvent(const BatteryInfo& info) const
251 {
252     bool isSuccess = true;
253 
254     if (info.GetCapacity() > lowCapacity_) {
255         g_batteryLowOnce = false;
256         return isSuccess;
257     }
258 
259     if (g_batteryLowOnce) {
260         return isSuccess;
261     }
262 
263     Want want;
264     want.SetAction(CommonEventSupport::COMMON_EVENT_BATTERY_LOW);
265     CommonEventData data;
266     data.SetWant(want);
267     CommonEventPublishInfo publishInfo;
268     publishInfo.SetOrdered(false);
269     data.SetCode(info.GetCapacity());
270     BATTERY_HILOGD(FEATURE_BATT_INFO, "publisher capacity=%{public}d", info.GetCapacity());
271     isSuccess = CommonEventManager::PublishCommonEvent(data, publishInfo);
272     if (!isSuccess) {
273         BATTERY_HILOGE(FEATURE_BATT_INFO, "failed to publish battery_low event");
274     }
275     g_batteryLowOnce = true;
276     return isSuccess;
277 }
278 
PublishOkayEvent(const BatteryInfo& info) const279 bool BatteryNotify::PublishOkayEvent(const BatteryInfo& info) const
280 {
281     bool isSuccess = true;
282 
283     if (info.GetCapacity() <= lowCapacity_) {
284         g_batteryOkOnce = false;
285         return isSuccess;
286     }
287 
288     if (g_batteryOkOnce) {
289         return isSuccess;
290     }
291 
292     Want want;
293     want.SetAction(CommonEventSupport::COMMON_EVENT_BATTERY_OKAY);
294     CommonEventData data;
295     data.SetWant(want);
296     CommonEventPublishInfo publishInfo;
297     publishInfo.SetOrdered(false);
298     data.SetCode(info.GetCapacity());
299     BATTERY_HILOGD(FEATURE_BATT_INFO, "publisher capacity=%{public}d", info.GetCapacity());
300     isSuccess = CommonEventManager::PublishCommonEvent(data, publishInfo);
301     if (!isSuccess) {
302         BATTERY_HILOGD(FEATURE_BATT_INFO, "failed to publish battery_okay event");
303     }
304     g_batteryOkOnce = true;
305     return isSuccess;
306 }
307 
PublishPowerConnectedEvent(const BatteryInfo& info) const308 bool BatteryNotify::PublishPowerConnectedEvent(const BatteryInfo& info) const
309 {
310     bool isSuccess = true;
311 
312     if ((info.GetPluggedType() == BatteryPluggedType::PLUGGED_TYPE_NONE) ||
313         (info.GetPluggedType() == BatteryPluggedType::PLUGGED_TYPE_BUTT)) {
314         g_batteryConnectOnce = false;
315         return isSuccess;
316     }
317 
318     if (g_batteryConnectOnce) {
319         return isSuccess;
320     }
321     StartVibrator();
322     Want want;
323     want.SetAction(CommonEventSupport::COMMON_EVENT_POWER_CONNECTED);
324     CommonEventData data;
325     data.SetWant(want);
326     CommonEventPublishInfo publishInfo;
327     publishInfo.SetOrdered(false);
328     data.SetCode(static_cast<int32_t>(info.GetPluggedType()));
329     BATTERY_HILOGD(FEATURE_BATT_INFO, "publisher pluggedtype=%{public}u",
330         static_cast<uint32_t>(info.GetPluggedType()));
331     isSuccess = CommonEventManager::PublishCommonEvent(data, publishInfo);
332     if (!isSuccess) {
333         BATTERY_HILOGE(FEATURE_BATT_INFO, "failed to publish power_connected event");
334     }
335 
336     g_batteryConnectOnce = true;
337     return isSuccess;
338 }
339 
StartVibrator() const340 void BatteryNotify::StartVibrator() const
341 {
342     std::shared_ptr<PowerVibrator> vibrator = PowerVibrator::GetInstance();
343     std::string scene = "start_charge";
344     vibrator->StartVibrator(scene);
345 }
346 
PublishPowerDisconnectedEvent(const BatteryInfo& info) const347 bool BatteryNotify::PublishPowerDisconnectedEvent(const BatteryInfo& info) const
348 {
349     bool isSuccess = true;
350 
351     if ((info.GetPluggedType() != BatteryPluggedType::PLUGGED_TYPE_NONE) &&
352         (info.GetPluggedType() != BatteryPluggedType::PLUGGED_TYPE_BUTT)) {
353         g_batteryDisconnectOnce = false;
354         return isSuccess;
355     }
356 
357     if (g_batteryDisconnectOnce) {
358         return isSuccess;
359     }
360 
361     Want want;
362     want.SetAction(CommonEventSupport::COMMON_EVENT_POWER_DISCONNECTED);
363     CommonEventData data;
364     data.SetWant(want);
365     CommonEventPublishInfo publishInfo;
366     publishInfo.SetOrdered(false);
367     data.SetCode(static_cast<int32_t>(info.GetPluggedType()));
368     BATTERY_HILOGD(FEATURE_BATT_INFO, "publisher pluggedtype=%{public}u",
369         static_cast<uint32_t>(info.GetPluggedType()));
370     isSuccess = CommonEventManager::PublishCommonEvent(data, publishInfo);
371     if (!isSuccess) {
372         BATTERY_HILOGD(FEATURE_BATT_INFO, "failed to publish power_disconnected event");
373     }
374 
375     g_batteryDisconnectOnce = true;
376     return isSuccess;
377 }
378 
PublishChargingEvent(const BatteryInfo& info) const379 bool BatteryNotify::PublishChargingEvent(const BatteryInfo& info) const
380 {
381     bool isSuccess = true;
382 
383     if ((info.GetChargeState() != BatteryChargeState::CHARGE_STATE_ENABLE) &&
384         (info.GetChargeState() != BatteryChargeState::CHARGE_STATE_FULL)) {
385         g_batteryChargingOnce = false;
386         return isSuccess;
387     }
388 
389     if (g_batteryChargingOnce) {
390         return isSuccess;
391     }
392 
393     Want want;
394     want.SetAction(CommonEventSupport::COMMON_EVENT_CHARGING);
395     CommonEventData data;
396     data.SetWant(want);
397     CommonEventPublishInfo publishInfo;
398     publishInfo.SetOrdered(false);
399     data.SetCode(static_cast<int32_t>(info.GetChargeState()));
400     BATTERY_HILOGD(FEATURE_BATT_INFO, "publisher chargeState=%{public}u",
401         static_cast<uint32_t>(info.GetChargeState()));
402     isSuccess = CommonEventManager::PublishCommonEvent(data, publishInfo);
403     if (!isSuccess) {
404         BATTERY_HILOGD(FEATURE_BATT_INFO, "failed to publish battery charing event");
405     }
406 
407     g_batteryChargingOnce = true;
408     return isSuccess;
409 }
410 
PublishDischargingEvent(const BatteryInfo& info) const411 bool BatteryNotify::PublishDischargingEvent(const BatteryInfo& info) const
412 {
413     bool isSuccess = true;
414 
415     if ((info.GetChargeState() == BatteryChargeState::CHARGE_STATE_ENABLE) ||
416         (info.GetChargeState() == BatteryChargeState::CHARGE_STATE_FULL)) {
417         g_batteryDischargingOnce = false;
418         return isSuccess;
419     }
420 
421     if (g_batteryDischargingOnce) {
422         return isSuccess;
423     }
424 
425     Want want;
426     want.SetAction(CommonEventSupport::COMMON_EVENT_DISCHARGING);
427     CommonEventData data;
428     data.SetWant(want);
429     CommonEventPublishInfo publishInfo;
430     publishInfo.SetOrdered(false);
431     data.SetCode(static_cast<int32_t>(info.GetChargeState()));
432     BATTERY_HILOGD(FEATURE_BATT_INFO, "publisher chargeState=%{public}u",
433         static_cast<uint32_t>(info.GetChargeState()));
434     isSuccess = CommonEventManager::PublishCommonEvent(data, publishInfo);
435     if (!isSuccess) {
436         BATTERY_HILOGD(FEATURE_BATT_INFO, "failed to publish battery charing event");
437     }
438 
439     g_batteryDischargingOnce = true;
440     return isSuccess;
441 }
442 
PublishCustomEvent(const BatteryInfo& info, const std::string& commonEventName) const443 bool BatteryNotify::PublishCustomEvent(const BatteryInfo& info, const std::string& commonEventName) const
444 {
445     Want want;
446     want.SetParam(BatteryInfo::COMMON_EVENT_KEY_UEVENT, info.GetUevent());
447     want.SetAction(commonEventName);
448     CommonEventData data;
449     data.SetWant(want);
450     CommonEventPublishInfo publishInfo;
451     publishInfo.SetOrdered(false);
452     const std::vector<std::string> permissionVec { "ohos.permission.POWER_OPTIMIZATION" };
453     publishInfo.SetSubscriberPermissions(permissionVec);
454 
455     bool isSuccess = CommonEventManager::PublishCommonEvent(data, publishInfo);
456     if (!isSuccess) {
457         BATTERY_HILOGD(FEATURE_BATT_INFO, "failed to publish battery custom event");
458     }
459     return isSuccess;
460 }
461 } // namespace PowerMgr
462 } // namespace OHOS
463