• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 "suspend_controller.h"
17 #include <datetime_ex.h>
18 #include <input_manager.h>
19 #include <securec.h>
20 #include <ipc_skeleton.h>
21 #include "power_log.h"
22 #include "ffrt_utils.h"
23 #include "power_mgr_service.h"
24 #include "power_state_callback_stub.h"
25 #include "setting_helper.h"
26 #include "system_suspend_controller.h"
27 #include "wakeup_controller.h"
28 
29 namespace OHOS {
30 namespace PowerMgr {
31 using namespace OHOS::MMI;
32 namespace {
33 sptr<SettingObserver> g_suspendSourcesKeyObserver = nullptr;
34 FFRTQueue g_queue("power_suspend_controller");
35 FFRTHandle g_sleepTimeoutHandle;
36 FFRTHandle g_userActivityOffTimeoutHandle;
37 FFRTUtils::Mutex g_monitorMutex;
38 } // namespace
39 
40 /** SuspendController Implement */
SuspendController(std::shared_ptr<ShutdownController> & shutdownController,std::shared_ptr<PowerStateMachine> & stateMachine)41 SuspendController::SuspendController(
42     std::shared_ptr<ShutdownController>& shutdownController, std::shared_ptr<PowerStateMachine>& stateMachine)
43 {
44     shutdownController_ = shutdownController;
45     stateMachine_ = stateMachine;
46 }
47 
~SuspendController()48 SuspendController::~SuspendController()
49 {
50     if (g_suspendSourcesKeyObserver) {
51         SettingHelper::UnregisterSettingSuspendSourcesObserver(g_suspendSourcesKeyObserver);
52     }
53 }
54 class SuspendPowerStateCallback : public PowerStateCallbackStub {
55 public:
SuspendPowerStateCallback(std::shared_ptr<SuspendController> controller)56     explicit SuspendPowerStateCallback(std::shared_ptr<SuspendController> controller) : controller_(controller) {};
57     virtual ~SuspendPowerStateCallback() = default;
OnPowerStateChanged(PowerState state)58     void OnPowerStateChanged(PowerState state) override
59     {
60         auto controller = controller_.lock();
61         if (controller == nullptr) {
62             POWER_HILOGI(FEATURE_SUSPEND, "OnPowerStateChanged: No controller");
63             return;
64         }
65         if (state == PowerState::AWAKE) {
66             POWER_HILOGI(FEATURE_SUSPEND, "Turn awake, stop sleep timer");
67             controller->StopSleep();
68         }
69     }
70 
71 private:
72     std::weak_ptr<SuspendController> controller_;
73 };
74 
Init()75 void SuspendController::Init()
76 {
77     std::shared_ptr<SuspendSources> sources = SuspendSourceParser::ParseSources();
78     sourceList_ = sources->GetSourceList();
79     if (sourceList_.empty()) {
80         POWER_HILOGE(FEATURE_SUSPEND, "InputManager is null");
81         return;
82     }
83 
84     for (auto source = sourceList_.begin(); source != sourceList_.end(); source++) {
85         POWER_HILOGI(FEATURE_SUSPEND, "registered type=%{public}u action=%{public}u delayMs=%{public}u",
86             (*source).GetReason(), (*source).GetAction(), (*source).GetDelay());
87         std::shared_ptr<SuspendMonitor> monitor = SuspendMonitor::CreateMonitor(*source);
88         if (monitor != nullptr && monitor->Init()) {
89             POWER_HILOGI(FEATURE_SUSPEND, "register type=%{public}u", (*source).GetReason());
90             monitor->RegisterListener(std::bind(&SuspendController::ControlListener, this, std::placeholders::_1,
91                 std::placeholders::_2, std::placeholders::_3));
92             g_monitorMutex.Lock();
93             monitorMap_.emplace(monitor->GetReason(), monitor);
94             g_monitorMutex.Unlock();
95         }
96     }
97     sptr<SuspendPowerStateCallback> callback = new SuspendPowerStateCallback(shared_from_this());
98     if (stateMachine_ == nullptr) {
99         POWER_HILOGE(FEATURE_SUSPEND, "Can't get PowerStateMachine");
100         return;
101     }
102     stateMachine_->RegisterPowerStateCallback(callback);
103     RegisterSettingsObserver();
104 }
105 
ExecSuspendMonitorByReason(SuspendDeviceType reason)106 void SuspendController::ExecSuspendMonitorByReason(SuspendDeviceType reason)
107 {
108     g_monitorMutex.Lock();
109     if (monitorMap_.find(reason) != monitorMap_.end()) {
110         auto monitor = monitorMap_[reason];
111         if (monitor == nullptr) {
112             POWER_HILOGI(COMP_SVC, "get monitor fail");
113             g_monitorMutex.Unlock();
114             return;
115         }
116         monitor->Notify();
117     }
118     g_monitorMutex.Unlock();
119 }
120 
RegisterSettingsObserver()121 void SuspendController::RegisterSettingsObserver()
122 {
123     if (g_suspendSourcesKeyObserver) {
124         POWER_HILOGE(FEATURE_POWER_STATE, "suspend sources key observer is already registered");
125         return;
126     }
127     SettingObserver::UpdateFunc updateFunc = [&](const std::string&) {
128         POWER_HILOGI(COMP_SVC, "start setting string update");
129         std::string jsonStr = SettingHelper::GetSettingSuspendSources();
130         std::shared_ptr<SuspendSources> sources = SuspendSourceParser::ParseSources(jsonStr);
131         std::vector<SuspendSource> updateSourceList = sources->GetSourceList();
132         if (updateSourceList.size() == 0) {
133             return;
134         }
135         sourceList_ = updateSourceList;
136         POWER_HILOGI(COMP_SVC, "start updateListener");
137         Cancel();
138         for (auto source = sourceList_.begin(); source != sourceList_.end(); source++) {
139             std::shared_ptr<SuspendMonitor> monitor = SuspendMonitor::CreateMonitor(*source);
140             if (monitor != nullptr && monitor->Init()) {
141                 monitor->RegisterListener(std::bind(&SuspendController::ControlListener, this, std::placeholders::_1,
142                     std::placeholders::_2, std::placeholders::_3));
143                 g_monitorMutex.Lock();
144                 monitorMap_.emplace(monitor->GetReason(), monitor);
145                 g_monitorMutex.Unlock();
146             }
147         }
148     };
149     g_suspendSourcesKeyObserver = SettingHelper::RegisterSettingSuspendSourcesObserver(updateFunc);
150     POWER_HILOGI(FEATURE_POWER_STATE, "register setting observer fin");
151 }
152 
Execute()153 void SuspendController::Execute()
154 {
155     HandleAction(GetLastReason(), GetLastAction());
156 }
157 
Cancel()158 void SuspendController::Cancel()
159 {
160     g_monitorMutex.Lock();
161     for (auto monitor = monitorMap_.begin(); monitor != monitorMap_.end(); monitor++) {
162         monitor->second->Cancel();
163     }
164     monitorMap_.clear();
165     g_monitorMutex.Unlock();
166 }
167 
StopSleep()168 void SuspendController::StopSleep()
169 {
170     if (sleepAction_ != static_cast<uint32_t>(SuspendAction::ACTION_NONE)) {
171         FFRTUtils::CancelTask(g_sleepTimeoutHandle, g_queue);
172         sleepTime_ = -1;
173         sleepAction_ = static_cast<uint32_t>(SuspendAction::ACTION_NONE);
174     }
175 }
176 
HandleEvent(int64_t delayTime)177 void SuspendController::HandleEvent(int64_t delayTime)
178 {
179     FFRTTask task = [&]() {
180         g_monitorMutex.Lock();
181         auto timeoutSuspendMonitor = monitorMap_.find(SuspendDeviceType::SUSPEND_DEVICE_REASON_TIMEOUT);
182         if (timeoutSuspendMonitor == monitorMap_.end()) {
183             g_monitorMutex.Unlock();
184             return;
185         }
186         g_monitorMutex.Unlock();
187         auto monitor = timeoutSuspendMonitor->second;
188         monitor->HandleEvent();
189     };
190     g_userActivityOffTimeoutHandle = FFRTUtils::SubmitDelayTask(task, delayTime, g_queue);
191 }
192 
CancelEvent()193 void SuspendController::CancelEvent()
194 {
195     FFRTUtils::CancelTask(g_userActivityOffTimeoutHandle, g_queue);
196 }
197 
RecordPowerKeyDown()198 void SuspendController::RecordPowerKeyDown()
199 {
200     if (stateMachine_ == nullptr) {
201         POWER_HILOGE(FEATURE_SUSPEND, "Can't get PowerStateMachine");
202         return;
203     }
204     bool isScreenOn = stateMachine_->IsScreenOn();
205     POWER_HILOGI(FEATURE_SUSPEND, "Suspend record key down action isScreenOn=%{public}d", isScreenOn);
206     if (!isScreenOn) {
207         powerkeyDownWhenScreenOff_ = true;
208     }
209 }
210 
GetPowerkeyDownWhenScreenOff()211 bool SuspendController::GetPowerkeyDownWhenScreenOff()
212 {
213     bool powerKeyDown = powerkeyDownWhenScreenOff_;
214     powerkeyDownWhenScreenOff_ = false;
215     return powerKeyDown;
216 }
217 
ControlListener(SuspendDeviceType reason,uint32_t action,uint32_t delay)218 void SuspendController::ControlListener(SuspendDeviceType reason, uint32_t action, uint32_t delay)
219 {
220     auto pms = DelayedSpSingleton<PowerMgrService>::GetInstance();
221     if (pms == nullptr) {
222         return;
223     }
224 
225     if (pms->CheckDialogAndShuttingDown()) {
226         return;
227     }
228 
229     if (!pms->IsScreenOn()) {
230         return;
231     }
232 
233     pid_t pid = IPCSkeleton::GetCallingPid();
234     auto uid = IPCSkeleton::GetCallingUid();
235     POWER_HILOGI(FEATURE_SUSPEND,
236         "Try to suspend device, pid=%{public}d, uid=%{public}d, reason=%{public}d, action=%{public}u, "
237         "delay=%{public}u" PRId32 "",
238         pid, uid, reason, action, delay);
239     bool force = true;
240     if (reason == SuspendDeviceType::SUSPEND_DEVICE_REASON_TIMEOUT) {
241         force = false;
242     }
243     if (stateMachine_ == nullptr) {
244         POWER_HILOGE(FEATURE_SUSPEND, "Can't get PowerStateMachine");
245         return;
246     }
247     bool ret = stateMachine_->SetState(
248         PowerState::INACTIVE, stateMachine_->GetReasionBySuspendType(static_cast<SuspendDeviceType>(reason)), force);
249     if (ret) {
250         StartSleepTimer(reason, action, delay);
251     }
252 }
253 
StartSleepTimer(SuspendDeviceType reason,uint32_t action,uint32_t delay)254 void SuspendController::StartSleepTimer(SuspendDeviceType reason, uint32_t action, uint32_t delay)
255 {
256     const int64_t& tmpRef = delay;
257     int64_t timeout = GetTickCount() + tmpRef;
258     if ((timeout > sleepTime_) && (sleepTime_ != -1)) {
259         POWER_HILOGI(FEATURE_SUSPEND, "already have a sleep event (%{public}" PRId64 " > %{public}" PRId64 ")", timeout,
260             sleepTime_);
261         return;
262     }
263     sleepTime_ = timeout;
264     sleepReason_ = reason;
265     sleepAction_ = action;
266     sleepDuration_ = delay;
267     if (delay == 0) {
268         HandleAction(reason, action);
269     } else {
270         FFRTTask task = [this] {
271             HandleAction(GetLastReason(), GetLastAction());
272         };
273         g_sleepTimeoutHandle = FFRTUtils::SubmitDelayTask(task, delay, g_queue);
274     }
275 }
276 
HandleAction(SuspendDeviceType reason,uint32_t action)277 void SuspendController::HandleAction(SuspendDeviceType reason, uint32_t action)
278 {
279     switch (static_cast<SuspendAction>(action)) {
280         case SuspendAction::ACTION_AUTO_SUSPEND:
281             HandleAutoSleep(reason);
282             break;
283         case SuspendAction::ACTION_FORCE_SUSPEND:
284             HandleForceSleep(reason);
285             break;
286         case SuspendAction::ACTION_HIBERNATE:
287             HandleHibernate(reason);
288             break;
289         case SuspendAction::ACTION_SHUTDOWN:
290             HandleShutdown(reason);
291             break;
292         case SuspendAction::ACTION_NONE:
293         default:
294             break;
295     }
296     sleepTime_ = -1;
297     sleepAction_ = static_cast<uint32_t>(SuspendAction::ACTION_NONE);
298 }
299 
HandleAutoSleep(SuspendDeviceType reason)300 void SuspendController::HandleAutoSleep(SuspendDeviceType reason)
301 {
302     POWER_HILOGI(FEATURE_SUSPEND, "auto suspend by reason=%{public}d", reason);
303 
304     if (stateMachine_ == nullptr) {
305         POWER_HILOGE(FEATURE_SUSPEND, "Can't get PowerStateMachine");
306         return;
307     }
308     bool ret = stateMachine_->SetState(
309         PowerState::SLEEP, stateMachine_->GetReasionBySuspendType(reason));
310     if (ret) {
311         POWER_HILOGI(FEATURE_SUSPEND, "State changed, set sleep timer");
312         SystemSuspendController::GetInstance().Suspend([]() {}, []() {}, false);
313     } else {
314         POWER_HILOGI(FEATURE_SUSPEND, "auto suspend: State change failed");
315     }
316 }
317 
HandleForceSleep(SuspendDeviceType reason)318 void SuspendController::HandleForceSleep(SuspendDeviceType reason)
319 {
320     POWER_HILOGI(FEATURE_SUSPEND, "force suspend by reason=%{public}d", reason);
321     if (stateMachine_ == nullptr) {
322         POWER_HILOGE(FEATURE_SUSPEND, "Can't get PowerStateMachine");
323         return;
324     }
325     bool ret = stateMachine_->SetState(
326         PowerState::SLEEP, stateMachine_->GetReasionBySuspendType(reason), true);
327     if (ret) {
328         POWER_HILOGI(FEATURE_SUSPEND, "State changed, system suspend");
329         SystemSuspendController::GetInstance().Suspend([]() {}, []() {}, true);
330     } else {
331         POWER_HILOGI(FEATURE_SUSPEND, "force suspend: State change failed");
332     }
333 }
334 
HandleHibernate(SuspendDeviceType reason)335 void SuspendController::HandleHibernate(SuspendDeviceType reason)
336 {
337     POWER_HILOGI(FEATURE_SUSPEND, "force suspend by reason=%{public}d", reason);
338     if (stateMachine_ == nullptr) {
339         POWER_HILOGE(FEATURE_SUSPEND, "Can't get PowerStateMachine");
340         return;
341     }
342     bool ret = stateMachine_->SetState(
343         PowerState::HIBERNATE, stateMachine_->GetReasionBySuspendType(reason), true);
344     if (ret) {
345         POWER_HILOGI(FEATURE_SUSPEND, "State changed, call hibernate");
346     } else {
347         POWER_HILOGI(FEATURE_SUSPEND, "Hibernate: State change failed");
348     }
349 }
350 
HandleShutdown(SuspendDeviceType reason)351 void SuspendController::HandleShutdown(SuspendDeviceType reason)
352 {
353     POWER_HILOGI(FEATURE_SUSPEND, "shutdown by reason=%{public}d", reason);
354     shutdownController_->Shutdown(std::to_string(static_cast<uint32_t>(reason)));
355 }
356 
CreateMonitor(SuspendSource & source)357 const std::shared_ptr<SuspendMonitor> SuspendMonitor::CreateMonitor(SuspendSource& source)
358 {
359     SuspendDeviceType reason = source.GetReason();
360     POWER_HILOGI(FEATURE_SUSPEND, "CreateMonitor reason=%{public}d", reason);
361     std::shared_ptr<SuspendMonitor> monitor = nullptr;
362     switch (reason) {
363         case SuspendDeviceType::SUSPEND_DEVICE_REASON_POWER_KEY:
364             monitor = std::static_pointer_cast<SuspendMonitor>(std::make_shared<PowerKeySuspendMonitor>(source));
365             break;
366         case SuspendDeviceType::SUSPEND_DEVICE_REASON_TIMEOUT:
367             monitor = std::static_pointer_cast<SuspendMonitor>(std::make_shared<TimeoutSuspendMonitor>(source));
368             break;
369         case SuspendDeviceType::SUSPEND_DEVICE_REASON_LID:
370             monitor = std::static_pointer_cast<SuspendMonitor>(std::make_shared<LidSuspendMonitor>(source));
371             break;
372         case SuspendDeviceType::SUSPEND_DEVICE_REASON_SWITCH:
373             monitor = std::static_pointer_cast<SuspendMonitor>(std::make_shared<SwitchSuspendMonitor>(source));
374             break;
375         default:
376             POWER_HILOGE(FEATURE_SUSPEND, "CreateMonitor : Invalid reason=%{public}d", reason);
377             break;
378     }
379     return monitor;
380 }
381 
382 /** PowerKeySuspendMonitor Implement */
Init()383 bool PowerKeySuspendMonitor::Init()
384 {
385     if (powerkeyReleaseId_ >= 0) {
386         return true;
387     }
388     std::shared_ptr<OHOS::MMI::KeyOption> keyOption = std::make_shared<OHOS::MMI::KeyOption>();
389     std::set<int32_t> preKeys;
390 
391     keyOption.reset();
392     keyOption = std::make_shared<OHOS::MMI::KeyOption>();
393     keyOption->SetPreKeys(preKeys);
394     keyOption->SetFinalKey(OHOS::MMI::KeyEvent::KEYCODE_POWER);
395     keyOption->SetFinalKeyDown(false);
396     keyOption->SetFinalKeyDownDuration(0);
397     powerkeyReleaseId_ = InputManager::GetInstance()->SubscribeKeyEvent(
398         keyOption, [this](std::shared_ptr<OHOS::MMI::KeyEvent> keyEvent) {
399             POWER_HILOGI(FEATURE_SUSPEND, "Receive key on notify");
400             auto pms = DelayedSpSingleton<PowerMgrService>::GetInstance();
401             if (pms == nullptr) {
402                 return;
403             }
404             std::shared_ptr<SuspendController> suspendController = pms->GetSuspendController();
405             if (suspendController->GetPowerkeyDownWhenScreenOff()) {
406                 POWER_HILOGI(FEATURE_SUSPEND, "no action suspend");
407                 return;
408             }
409             Notify();
410         });
411     POWER_HILOGI(FEATURE_SUSPEND, "powerkeyReleaseId_=%{public}d", powerkeyReleaseId_);
412     return powerkeyReleaseId_ >= 0 ? true : false;
413 }
414 
Cancel()415 void PowerKeySuspendMonitor::Cancel()
416 {
417     if (powerkeyReleaseId_ >= 0) {
418         InputManager::GetInstance()->UnsubscribeKeyEvent(powerkeyReleaseId_);
419         powerkeyReleaseId_ = -1;
420     }
421 }
422 
423 /** Timeout Implement */
Init()424 bool TimeoutSuspendMonitor::Init()
425 {
426     return true;
427 }
428 
Cancel()429 void TimeoutSuspendMonitor::Cancel() {}
430 
HandleEvent()431 void TimeoutSuspendMonitor::HandleEvent()
432 {
433     POWER_HILOGI(FEATURE_INPUT, "TimeoutSuspendMonitor HandleEvent");
434     Notify();
435 }
436 
437 /** LidSuspendMonitor Implement */
438 
Init()439 bool LidSuspendMonitor::Init()
440 {
441     return true;
442 }
443 
Cancel()444 void LidSuspendMonitor::Cancel() {}
445 
446 /** SwitchSuspendMonitor Implement */
447 
Init()448 bool SwitchSuspendMonitor::Init()
449 {
450     return true;
451 }
452 
Cancel()453 void SwitchSuspendMonitor::Cancel() {}
454 
455 } // namespace PowerMgr
456 } // namespace OHOS
457