• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "charger_thread.h"
17 #include "battery_config.h"
18 #include "charger_log.h"
19 #include "charger_animation.h"
20 #include "init_reboot.h"
21 #include <cstdint>
22 #include <input_manager.h>
23 #include <cinttypes>
24 #include <linux/netlink.h>
25 #include <parameters.h>
26 #include <securec.h>
27 #include <dlfcn.h>
28 
29 using namespace OHOS::MMI;
30 
31 namespace OHOS {
32 namespace PowerMgr {
33 namespace {
34 constexpr int32_t SEC_TO_MSEC = 1000;
35 constexpr int32_t NSEC_TO_MSEC = 1000000;
36 constexpr int32_t REBOOT_TIME = 2000;
37 constexpr int32_t BACKLIGHT_OFF_TIME_MS = 10000;
38 constexpr int32_t VIBRATE_TIME_MS = 75;
39 const std::string REBOOT_CMD = "";
40 const std::string SHUTDOWN_CMD = "shutdown";
41 constexpr int32_t KEY_ACTION_DOWN_VAL = 1;
42 constexpr int32_t KEY_ACTION_UP_VAL = 0;
43 } // namespace
44 
45 std::unique_ptr<ChargerAnimation> ChargerThread::animation_ = nullptr;
46 bool ChargerThread::isChargeStateChanged_ = false;
47 bool ChargerThread::isConfigParse_ = false;
48 int32_t ChargerThread::lackPowerCapacity_ = -1;
49 
50 struct KeyState {
51     bool isUp;
52     bool isDown;
53     int64_t timestamp;
54 };
55 struct KeyState g_keys[KEY_MAX + 1] = {};
56 
57 static const char* POWER_CHARGE_EXTENSION_PATH = "libpower_charge_ext.z.so";
58 static const char* CLEAR_POWER_OFF_CHARGE_FLAG_FUNC = "ClearPowerOffChargeFlag";
59 typedef void(*Func)();
60 
ClearPowerOffChargeFlag()61 static void ClearPowerOffChargeFlag()
62 {
63     BATTERY_HILOGI(FEATURE_CHARGING, "enter ClearPowerOffChargeFlag");
64     void *handler = dlopen(POWER_CHARGE_EXTENSION_PATH, RTLD_LAZY | RTLD_NODELETE);
65     if (handler == nullptr) {
66         BATTERY_HILOGE(FEATURE_CHARGING, "Dlopen failed, reason : %{public}s", dlerror());
67         return;
68     }
69 
70     Func clearPowerOffChargeFlag = (Func)dlsym(handler, CLEAR_POWER_OFF_CHARGE_FLAG_FUNC);
71     if (clearPowerOffChargeFlag == nullptr) {
72         BATTERY_HILOGE(FEATURE_CHARGING, "find function failed, reason : %{public}s", dlerror());
73         dlclose(handler);
74         return;
75     }
76     clearPowerOffChargeFlag();
77     dlclose(handler);
78 }
79 
GetCurrentTime()80 static int64_t GetCurrentTime()
81 {
82     timespec tm {};
83     clock_gettime(CLOCK_MONOTONIC, &tm);
84     return tm.tv_sec * SEC_TO_MSEC + (tm.tv_nsec / NSEC_TO_MSEC);
85 }
86 
SetKeyState(int32_t code,int32_t value,int64_t now) const87 void ChargerThreadInputMonitor::SetKeyState(int32_t code, int32_t value, int64_t now) const
88 {
89     bool isDown = !!value;
90 
91     if (code > KEY_MAX) {
92         BATTERY_HILOGW(FEATURE_CHARGING, "code lager than KEY_MAX: %{public}d", code);
93         return;
94     }
95 
96     if (g_keys[code].isDown == isDown) {
97         BATTERY_HILOGW(FEATURE_CHARGING, "PowerKey is already down");
98         return;
99     }
100 
101     if (isDown) {
102         g_keys[code].timestamp = now;
103     }
104 
105     g_keys[code].isDown = isDown;
106     g_keys[code].isUp = true;
107 }
108 
HandleStates()109 void ChargerThread::HandleStates()
110 {
111     HandleChargingState();
112     HandlePowerKeyState();
113     HandleScreenState();
114 }
115 
UpdateWaitInterval()116 int32_t ChargerThread::UpdateWaitInterval()
117 {
118     int64_t currentTime = GetCurrentTime();
119     int64_t nextWait = INT64_MAX;
120     int64_t timeout = INVALID;
121 
122     if (keyWait_ != INVALID && keyWait_ < nextWait) {
123         nextWait = keyWait_;
124     }
125 
126     if (backlightWait_ != INVALID && backlightWait_ < nextWait) {
127         nextWait = backlightWait_;
128     }
129 
130     if (nextWait != INVALID && nextWait != INT64_MAX) {
131         if (nextWait - currentTime > 0) {
132             timeout = nextWait - currentTime;
133         } else {
134             timeout = 0;
135         }
136     }
137 
138     return static_cast<int32_t>(timeout);
139 }
140 
CycleMatters()141 void ChargerThread::CycleMatters()
142 {
143     if (!started_) {
144         started_ = true;
145         backlightWait_ = GetCurrentTime() - 1;
146     }
147 
148     UpdateBatteryInfo(nullptr);
149     BATTERY_HILOGD(FEATURE_CHARGING, "chargeState_=%{public}d, capacity_=%{public}d", chargeState_, capacity_);
150     UpdateEpollInterval(chargeState_);
151 }
152 
UpdateBatteryInfo(void * arg)153 void ChargerThread::UpdateBatteryInfo(void* arg)
154 {
155     BATTERY_HILOGD(FEATURE_CHARGING, "start update battery info by provider");
156     int32_t temperature = 0;
157     provider_->ParseTemperature(&temperature);
158     provider_->ParseCapacity(&capacity_);
159     int32_t oldChargeState = chargeState_;
160     provider_->ParseChargeState(&chargeState_);
161     BATTERY_HILOGD(FEATURE_CHARGING, "temperature=%{public}d, capacity_=%{public}d, chargeState_=%{public}d",
162         temperature, capacity_, chargeState_);
163     if (chargeState_ != oldChargeState) {
164         isChargeStateChanged_ = true;
165     } else {
166         isChargeStateChanged_ = false;
167     }
168 
169     HandleTemperature(temperature);
170     HandleCapacity(capacity_);
171 
172     led_->UpdateColor(chargeState_, capacity_);
173 
174     if (backlight_->GetScreenState() == BatteryBacklight::SCREEN_ON) {
175         UpdateAnimation(chargeState_, capacity_);
176     }
177 }
178 
HandleTemperature(const int32_t & temperature)179 void ChargerThread::HandleTemperature(const int32_t& temperature)
180 {
181     const int32_t DEFAULT_UPPER_TEMP_CONF = INT32_MAX;
182     const int32_t DEFAULT_LOWER_TEMP_CONF = INT32_MIN;
183     auto& batteryConfig = BatteryConfig::GetInstance();
184     auto highTemp = batteryConfig.GetInt("temperature.high", DEFAULT_UPPER_TEMP_CONF);
185     auto lowTemp = batteryConfig.GetInt("temperature.low", DEFAULT_LOWER_TEMP_CONF);
186     BATTERY_HILOGD(FEATURE_CHARGING, "temperature=%{public}d, lowTemp=%{public}d, highTemp=%{public}d", temperature,
187         lowTemp, highTemp);
188 
189     if (((temperature <= lowTemp) || (temperature >= highTemp)) && (lowTemp != highTemp)) {
190         BATTERY_HILOGW(FEATURE_CHARGING, "temperature out of range, shutdown device");
191         DoReboot(SHUTDOWN_CMD.c_str());
192     }
193 }
194 
HandleCapacity(const int32_t & capacity)195 void ChargerThread::HandleCapacity(const int32_t& capacity)
196 {
197     if (capacity > lackPowerCapacity_ &&
198         (chargeState_ == PowerSupplyProvider::CHARGE_STATE_DISABLE ||
199             chargeState_ == PowerSupplyProvider::CHARGE_STATE_NONE)) {
200         BATTERY_HILOGW(FEATURE_CHARGING, "Not Charging, Shutdown system");
201         DoReboot(SHUTDOWN_CMD.c_str());
202     }
203 }
204 
UpdateAnimation(const int32_t & chargeState,const int32_t & capacity)205 void ChargerThread::UpdateAnimation(const int32_t& chargeState, const int32_t& capacity)
206 {
207     BATTERY_HILOGD(FEATURE_CHARGING, "start update animation, capacity=%{public}d", capacity);
208     if ((chargeState == PowerSupplyProvider::CHARGE_STATE_NONE) ||
209         (chargeState == PowerSupplyProvider::CHARGE_STATE_RESERVED)) {
210         BATTERY_HILOGD(FEATURE_CHARGING, "Unknown charge state");
211         return;
212     }
213 
214     if (capacity <= lackPowerCapacity_) {
215         if (chargeState == PowerSupplyProvider::CHARGE_STATE_ENABLE) { // Charging state
216             BATTERY_HILOGD(FEATURE_CHARGING, "Lack power");
217             animation_->AnimationStop();
218             animation_->LackPowerNotChargingPromptStop();
219             animation_->LackPowerChargingPromptStart();
220         } else if (chargeState == PowerSupplyProvider::CHARGE_STATE_DISABLE) { // Not charging state
221             BATTERY_HILOGD(FEATURE_CHARGING, "Lack power, please connect charger");
222             animation_->AnimationStop();
223             animation_->LackPowerChargingPromptStop();
224             animation_->LackPowerNotChargingPromptStart();
225         } else {
226             BATTERY_HILOGD(FEATURE_CHARGING, "capacity=%{public}d, chargeState=%{public}d", capacity, chargeState);
227         }
228     } else if (chargeState == PowerSupplyProvider::CHARGE_STATE_ENABLE ||
229         chargeState == PowerSupplyProvider::CHARGE_STATE_FULL) { // Charging state
230         BATTERY_HILOGD(FEATURE_CHARGING, "Display animation according capacity");
231         animation_->LackPowerChargingPromptStop();
232         animation_->LackPowerNotChargingPromptStop();
233         animation_->AnimationStart(capacity);
234     }
235 }
236 
InitAnimation()237 void ChargerThread::InitAnimation()
238 {
239     animation_ = std::make_unique<ChargerAnimation>();
240     animation_->InitConfig();
241 }
242 
SetKeyWait(struct KeyState & key,int64_t timeout)243 void ChargerThread::SetKeyWait(struct KeyState& key, int64_t timeout)
244 {
245     int64_t nextMoment = key.timestamp + timeout;
246     if (keyWait_ == INVALID || nextMoment < keyWait_) {
247         keyWait_ = nextMoment;
248     }
249 }
250 
HandleChargingState()251 void ChargerThread::HandleChargingState()
252 {
253     if ((chargeState_ == PowerSupplyProvider::CHARGE_STATE_NONE) ||
254         (chargeState_ == PowerSupplyProvider::CHARGE_STATE_RESERVED)) {
255         return;
256     }
257 
258     if (isChargeStateChanged_) {
259         BATTERY_HILOGD(FEATURE_CHARGING, "Charging State has changed");
260         backlight_->TurnOnScreen();
261         backlightWait_ = GetCurrentTime() - 1;
262         UpdateAnimation(chargeState_, capacity_);
263         isChargeStateChanged_ = false;
264     }
265 }
266 
HandleScreenState()267 void ChargerThread::HandleScreenState()
268 {
269     if (backlightWait_ != INVALID && GetCurrentTime() > backlightWait_ + BACKLIGHT_OFF_TIME_MS) {
270         backlight_->TurnOffScreen();
271         animation_->AnimationStop();
272         animation_->LackPowerChargingPromptStop();
273         animation_->LackPowerNotChargingPromptStop();
274         backlightWait_ = INVALID;
275     }
276 }
277 
HandlePowerKeyState()278 void ChargerThread::HandlePowerKeyState()
279 {
280     auto now = GetCurrentTime();
281     HandlePowerKey(KEY_POWER, now);
282 
283     BATTERY_HILOGD(FEATURE_CHARGING, "keyWait_=%{public}" PRId64 "", keyWait_);
284     if (keyWait_ != INVALID && now > keyWait_) {
285         keyWait_ = INVALID;
286     }
287 }
288 
HandlePowerKey(int32_t keycode,int64_t now)289 void ChargerThread::HandlePowerKey(int32_t keycode, int64_t now)
290 {
291     if (keycode == KEY_POWER) {
292         static bool turnOnByKeydown = false;
293         if (g_keys[keycode].isDown) {
294             int64_t rebootTime = g_keys[keycode].timestamp + REBOOT_TIME;
295             if (now >= rebootTime) {
296                 BATTERY_HILOGW(FEATURE_CHARGING, "reboot machine");
297                 backlight_->TurnOffScreen();
298                 vibrate_->HandleVibration(VIBRATE_TIME_MS);
299                 ClearPowerOffChargeFlag();
300                 DoReboot(REBOOT_CMD.c_str());
301             } else if (backlight_->GetScreenState() == BatteryBacklight::SCREEN_OFF) {
302                 SetKeyWait(g_keys[keycode], REBOOT_TIME);
303                 backlight_->TurnOnScreen();
304                 UpdateAnimation(chargeState_, capacity_);
305                 backlightWait_ = now - 1;
306                 turnOnByKeydown = true;
307             }
308         } else if (g_keys[keycode].isUp) {
309             if (backlight_->GetScreenState() == BatteryBacklight::SCREEN_ON && !turnOnByKeydown) {
310                 backlight_->TurnOffScreen();
311                 animation_->AnimationStop();
312                 animation_->LackPowerChargingPromptStop();
313                 animation_->LackPowerNotChargingPromptStop();
314                 backlightWait_ = INVALID;
315             } else {
316                 backlight_->TurnOnScreen();
317                 backlightWait_ = now - 1;
318                 UpdateAnimation(chargeState_, capacity_);
319             }
320             g_keys[keycode].isUp = false;
321             turnOnByKeydown = false;
322         }
323     }
324 }
325 
OnInputEvent(std::shared_ptr<OHOS::MMI::PointerEvent> pointerEvent) const326 void ChargerThreadInputMonitor::OnInputEvent(std::shared_ptr<OHOS::MMI::PointerEvent> pointerEvent) const {};
OnInputEvent(std::shared_ptr<OHOS::MMI::AxisEvent> axisEvent) const327 void ChargerThreadInputMonitor::OnInputEvent(std::shared_ptr<OHOS::MMI::AxisEvent> axisEvent) const {};
328 
OnInputEvent(std::shared_ptr<OHOS::MMI::KeyEvent> keyEvent) const329 void ChargerThreadInputMonitor::OnInputEvent(std::shared_ptr<OHOS::MMI::KeyEvent> keyEvent) const
330 {
331     if (keyEvent->GetKeyCode() == OHOS::MMI::KeyEvent::KEYCODE_POWER) {
332         if (keyEvent->GetKeyAction() == MMI::KeyEvent::KEY_ACTION_DOWN) {
333             BATTERY_HILOGI(FEATURE_CHARGING, "PowerKey Action Down");
334             SetKeyState(KEY_POWER, KEY_ACTION_DOWN_VAL, GetCurrentTime());
335         } else if (keyEvent->GetKeyAction() == MMI::KeyEvent::KEY_ACTION_UP) {
336             BATTERY_HILOGI(FEATURE_CHARGING, "PowerKey Action Up");
337             SetKeyState(KEY_POWER, KEY_ACTION_UP_VAL, GetCurrentTime());
338         }
339     }
340 }
341 
InputMonitorInit()342 void ChargerThread::InputMonitorInit()
343 {
344     BATTERY_HILOGI(FEATURE_CHARGING, "Charger input monitor init");
345     std::shared_ptr<ChargerThreadInputMonitor> inputMonitor = std::make_shared<ChargerThreadInputMonitor>();
346     if (inputMonitorId_ < 0) {
347         inputMonitorId_ =
348             InputManager::GetInstance()->AddMonitor(std::static_pointer_cast<IInputEventConsumer>(inputMonitor));
349     }
350 }
351 
InputMonitorCancel()352 void ChargerThread::InputMonitorCancel()
353 {
354     BATTERY_HILOGI(FEATURE_CHARGING, "Charger input monitor cancel");
355     InputManager *inputManager = InputManager::GetInstance();
356     if (inputMonitorId_ >= 0) {
357         inputManager->RemoveMonitor(inputMonitorId_);
358         inputMonitorId_ = -1;
359     }
360 }
361 
InitLackPowerCapacity()362 void ChargerThread::InitLackPowerCapacity()
363 {
364     if (!isConfigParse_) {
365         isConfigParse_ = BatteryConfig::GetInstance().ParseConfig();
366     }
367 
368     auto& batteryConfig = BatteryConfig::GetInstance();
369     lackPowerCapacity_ = batteryConfig.GetInt("soc.shutdown");
370     BATTERY_HILOGD(FEATURE_CHARGING, "lackPowerCapacity_ = %{public}d", lackPowerCapacity_);
371 }
372 
InitBatteryFileSystem()373 void ChargerThread::InitBatteryFileSystem()
374 {
375     provider_ = std::make_unique<PowerSupplyProvider>();
376     if (provider_ == nullptr) {
377         BATTERY_HILOGE(FEATURE_CHARGING, "make_unique PowerSupplyProvider return nullptr");
378         return;
379     }
380     provider_->InitBatteryPath();
381     provider_->InitPowerSupplySysfs();
382 }
383 
InitVibration()384 void ChargerThread::InitVibration()
385 {
386     vibrate_ = std::make_unique<BatteryVibrate>();
387     if (vibrate_ == nullptr) {
388         BATTERY_HILOGE(FEATURE_CHARGING, "make_unique BatteryVibrate return nullptr");
389         return;
390     }
391 
392     if (!vibrate_->InitVibration()) {
393         BATTERY_HILOGW(FEATURE_CHARGING, "InitVibration failed, vibration does not work");
394     }
395 }
396 
InitBacklight()397 void ChargerThread::InitBacklight()
398 {
399     backlight_ = std::make_unique<BatteryBacklight>();
400     if (backlight_ == nullptr) {
401         BATTERY_HILOGE(FEATURE_CHARGING, "make_unique BatteryBacklight return nullptr");
402         return;
403     }
404     backlight_->TurnOnScreen();
405 }
406 
InitLed()407 void ChargerThread::InitLed()
408 {
409     led_ = std::make_unique<BatteryLed>();
410     if (led_ == nullptr) {
411         BATTERY_HILOGE(FEATURE_CHARGING, "make_unique BatteryLed return nullptr");
412         return;
413     }
414 
415     if (!isConfigParse_) {
416         isConfigParse_ = BatteryConfig::GetInstance().ParseConfig();
417     }
418     led_->InitLight();
419     led_->TurnOff();
420 }
421 
Init()422 void ChargerThread::Init()
423 {
424     BATTERY_HILOGD(FEATURE_CHARGING, "start init charger thread");
425     InitLackPowerCapacity();
426     InitBatteryFileSystem();
427     InitVibration();
428     InitBacklight();
429     InitLed();
430     InitAnimation();
431     InputMonitorInit();
432 }
433 
Run(void * service)434 void ChargerThread::Run(void* service)
435 {
436     BATTERY_HILOGI(FEATURE_CHARGING, "start run charger thread");
437     Init();
438     std::make_unique<std::thread>([this, service] { this->LoopingThreadEntry(service); })->join();
439 }
440 } // namespace PowerMgr
441 } // namespace OHOS
442