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