• 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 "device_state_action.h"
17 
18 #include <mutex>
19 #include <condition_variable>
20 #include <ipc_skeleton.h>
21 #include "display_power_mgr_client.h"
22 #include "power_log.h"
23 #include "power_state_machine_info.h"
24 #include "power_utils.h"
25 #include "system_suspend_controller.h"
26 
27 using namespace std;
28 
29 namespace OHOS {
30 namespace PowerMgr {
31 using namespace DisplayPowerMgr;
32 using namespace Rosen;
33 
DeviceStateAction()34 DeviceStateAction::DeviceStateAction()
35 {
36     dispCallback_ = new DisplayPowerCallback();
37 }
38 
~DeviceStateAction()39 DeviceStateAction::~DeviceStateAction()
40 {
41     dispCallback_ = nullptr;
42 }
43 
Suspend(int64_t callTimeMs,SuspendDeviceType type,uint32_t flags)44 void DeviceStateAction::Suspend(int64_t callTimeMs, SuspendDeviceType type, uint32_t flags)
45 {
46     // Display is controlled by PowerStateMachine
47     // Don't suspend until GoToSleep is called
48 }
49 
ForceSuspend()50 void DeviceStateAction::ForceSuspend()
51 {
52     GoToSleep(nullptr, nullptr, true);
53 }
54 
Wakeup(int64_t callTimeMs,WakeupDeviceType type,const string & details,const string & pkgName)55 void DeviceStateAction::Wakeup(int64_t callTimeMs, WakeupDeviceType type, const string& details,
56     const string& pkgName)
57 {
58     SystemSuspendController::GetInstance().Wakeup();
59 }
60 
GetDisplayState()61 DisplayState DeviceStateAction::GetDisplayState()
62 {
63     DisplayPowerMgr::DisplayState state = DisplayPowerMgrClient::GetInstance().GetDisplayState();
64     POWER_HILOGD(FEATURE_POWER_STATE, "Get display state: %{public}d", state);
65     DisplayState ret = DisplayState::DISPLAY_UNKNOWN;
66     switch (state) {
67         case DisplayPowerMgr::DisplayState::DISPLAY_ON:
68             ret = DisplayState::DISPLAY_ON;
69             break;
70         case DisplayPowerMgr::DisplayState::DISPLAY_DIM:
71             ret = DisplayState::DISPLAY_DIM;
72             break;
73         case DisplayPowerMgr::DisplayState::DISPLAY_OFF:
74             ret = DisplayState::DISPLAY_OFF;
75             break;
76         case DisplayPowerMgr::DisplayState::DISPLAY_DOZE:
77             ret = DisplayState::DISPLAY_DOZE;
78             break;
79         case DisplayPowerMgr::DisplayState::DISPLAY_DOZE_SUSPEND:
80             ret = DisplayState::DISPLAY_DOZE_SUSPEND;
81             break;
82         case DisplayPowerMgr::DisplayState::DISPLAY_SUSPEND:
83             ret = DisplayState::DISPLAY_SUSPEND;
84             break;
85         case DisplayPowerMgr::DisplayState::DISPLAY_UNKNOWN:
86             ret = DisplayState::DISPLAY_UNKNOWN;
87             break;
88         default:
89             break;
90     }
91     return ret;
92 }
93 
TryToCancelScreenOff()94 bool DeviceStateAction::TryToCancelScreenOff()
95 {
96     POWER_HILOGI(FEATURE_POWER_STATE, "[UL_POWER]ready to call TryToCancelScreenOff");
97     std::unique_lock lock(cancelScreenOffMutex_);
98     POWER_HILOGI(FEATURE_POWER_STATE, "[UL_POWER]TryToCancelScreenOff mutex acquired");
99     if (!screenOffStarted_) {
100         POWER_HILOGI(FEATURE_POWER_STATE, "[UL_POWER]powerkey screen off not in progress");
101         return false;
102     }
103     interruptingScreenOff_ = true;
104     // block thread until suspendbegin
105     constexpr uint32_t timeoutMs = 300;
106     bool notified = cancelScreenOffCv_.wait_for(lock, std::chrono::milliseconds(timeoutMs), [this] {
107         return cancelScreenOffCvUnblocked_;
108     });
109     if (!notified) {
110         POWER_HILOGW(FEATURE_POWER_STATE, "[UL_POWER]TryToCancelScreenOff wait for response timed out");
111     }
112     if (screenOffInterrupted_) {
113         //not really calling the interface of DMS, interrupted early instead
114         POWER_HILOGI(FEATURE_POWER_STATE, "[UL_POWER]Interrupted before calling SuspendBegin");
115         return true;
116     }
117     POWER_HILOGI(FEATURE_POWER_STATE, "[UL_POWER]calling TryToCancelScreenOff");
118     screenOffInterrupted_ = DisplayManagerLite::GetInstance().TryToCancelScreenOff();
119     return screenOffInterrupted_;
120 }
121 
BeginPowerkeyScreenOff()122 void DeviceStateAction::BeginPowerkeyScreenOff()
123 {
124     POWER_HILOGI(FEATURE_POWER_STATE, "[UL_POWER]BeginPowerkeyScreenOff");
125     std::lock_guard lock(cancelScreenOffMutex_);
126     screenOffStarted_ = true;
127     cancelScreenOffCvUnblocked_ = false;
128     interruptingScreenOff_ = false;
129     screenOffInterrupted_ = false;
130 }
131 
EndPowerkeyScreenOff()132 void DeviceStateAction::EndPowerkeyScreenOff()
133 {
134     POWER_HILOGI(FEATURE_POWER_STATE, "[UL_POWER]EndPowerkeyScreenOff");
135     std::unique_lock lock(cancelScreenOffMutex_);
136     screenOffStarted_ = false;
137     cancelScreenOffCvUnblocked_ = true;
138     interruptingScreenOff_ = false;
139     screenOffInterrupted_ = false;
140     lock.unlock();
141     cancelScreenOffCv_.notify_all();
142 }
143 
IsInterruptingScreenOff(PowerStateChangeReason dispReason)144 bool DeviceStateAction::IsInterruptingScreenOff(PowerStateChangeReason dispReason)
145 {
146     bool ret = false;
147     POWER_HILOGI(FEATURE_POWER_STATE, "[UL_POWER]IsInterruptingScreenOff, dispReason: %{public}d", dispReason);
148     if (dispReason == PowerStateChangeReason::STATE_CHANGE_REASON_HARD_KEY) {
149         std::unique_lock lock(cancelScreenOffMutex_);
150         if (screenOffStarted_ && interruptingScreenOff_) {
151             POWER_HILOGI(FEATURE_POWER_STATE, "[UL_POWER]powerkey screen off interrupted before SuspendBegin");
152             ret = true;
153             // If there is a powerkey screen off event on going, tell the blocked thread that this function has been
154             // executed and has observed interruptingScreenOff_ set by TryToCancelScreenOff.
155             // The screen off action will be interrupted inside our own process without calling DMS interfaces
156             // and it would be safe for TryToCancelScreenOff to return true.
157             screenOffInterrupted_ = true;
158         } else {
159             // Otherwise calls SuspendBegin before unblocking TryToCancelScreenOff to reduce the possibility for
160             // TryToCancelScreenOff to fail.
161             DisplayManagerLite::GetInstance().SuspendBegin(dispReason);
162         }
163         cancelScreenOffCvUnblocked_ = true;
164         lock.unlock();
165         cancelScreenOffCv_.notify_all();
166     } else {
167         // not in the process of a powerkey screen off, calls SuspendBegin as usual
168         DisplayManagerLite::GetInstance().SuspendBegin(dispReason);
169     }
170     return ret;
171 }
172 
GetDisplayPowerMgrDisplayState(DisplayState state)173 DisplayPowerMgr::DisplayState DeviceStateAction::GetDisplayPowerMgrDisplayState(DisplayState state)
174 {
175     DisplayPowerMgr::DisplayState ret = DisplayPowerMgr::DisplayState::DISPLAY_UNKNOWN;
176     switch (state) {
177         case DisplayState::DISPLAY_ON:
178             ret = DisplayPowerMgr::DisplayState::DISPLAY_ON;
179             break;
180         case DisplayState::DISPLAY_DIM:
181             ret = DisplayPowerMgr::DisplayState::DISPLAY_DIM;
182             break;
183         case DisplayState::DISPLAY_OFF:
184             ret = DisplayPowerMgr::DisplayState::DISPLAY_OFF;
185             break;
186         case DisplayState::DISPLAY_DOZE:
187             ret = DisplayPowerMgr::DisplayState::DISPLAY_DOZE;
188             break;
189         case DisplayState::DISPLAY_DOZE_SUSPEND:
190             ret = DisplayPowerMgr::DisplayState::DISPLAY_DOZE_SUSPEND;
191             break;
192         case DisplayState::DISPLAY_SUSPEND:
193             ret = DisplayPowerMgr::DisplayState::DISPLAY_SUSPEND;
194             break;
195         default:
196             ret = DisplayPowerMgr::DisplayState::DISPLAY_UNKNOWN;
197             break;
198     }
199     return ret;
200 }
201 
IsOnState(DisplayState state)202 bool DeviceStateAction::IsOnState(DisplayState state)
203 {
204     return state == DisplayState::DISPLAY_ON || state == DisplayState::DISPLAY_DIM;
205 }
206 
SetDisplayState(DisplayState state,StateChangeReason reason)207 uint32_t DeviceStateAction::SetDisplayState(DisplayState state, StateChangeReason reason)
208 {
209     DisplayState currentState = GetDisplayState();
210     if (state == currentState && reason != StateChangeReason::STATE_CHANGE_REASON_PRE_BRIGHT_AUTH_FAIL_SCREEN_OFF) {
211         POWER_HILOGD(FEATURE_POWER_STATE, "Already in state: %{public}d", static_cast<uint32_t>(state));
212         return ActionResult::SUCCESS;
213     }
214     if (!isRegister_) {
215         isRegister_ = DisplayPowerMgrClient::GetInstance().RegisterCallback(dispCallback_);
216     }
217     if (reason == StateChangeReason::STATE_CHANGE_REASON_PRE_BRIGHT_AUTH_FAIL_SCREEN_OFF) {
218         if (currentState == DisplayState::DISPLAY_ON || currentState == DisplayState::DISPLAY_DIM) {
219             return ActionResult::SUCCESS;
220         }
221         currentState = DisplayState::DISPLAY_ON;
222     }
223     DisplayPowerMgr::DisplayState dispState = GetDisplayPowerMgrDisplayState(state);
224     PowerStateChangeReason dispReason = PowerUtils::GetDmsReasonByPowerReason(reason);
225     switch (state) {
226         case DisplayState::DISPLAY_ON: {
227             if (!IsOnState(currentState)) {
228                 std::string identity = IPCSkeleton::ResetCallingIdentity();
229                 DisplayManagerLite::GetInstance().WakeUpBegin(dispReason);
230                 IPCSkeleton::SetCallingIdentity(identity);
231             }
232             break;
233         }
234         case DisplayState::DISPLAY_DOZE:
235         case DisplayState::DISPLAY_OFF: {
236             if (IsOnState(currentState)) {
237                 std::string identity = IPCSkeleton::ResetCallingIdentity();
238                 // SuspendBegin is processed inside IsInterruptingScreenOff
239                 if (IsInterruptingScreenOff(dispReason)) {
240                     return ActionResult::FAILED;
241                 }
242                 IPCSkeleton::SetCallingIdentity(identity);
243             }
244             break;
245         }
246         default:
247             break;
248     }
249     dispCallback_->notify_ = actionCallback_;
250     bool ret = DisplayPowerMgrClient::GetInstance().SetDisplayState(dispState, reason);
251     POWER_HILOGI(FEATURE_POWER_STATE, "Set display state finished, ret=%{public}d", ret);
252     return ret ? ActionResult::SUCCESS : ActionResult::FAILED;
253 }
254 
SetInternalScreenDisplayPower(DisplayState state,StateChangeReason reason)255 void DeviceStateAction::SetInternalScreenDisplayPower(DisplayState state, StateChangeReason reason)
256 {
257     POWER_HILOGI(
258         FEATURE_POWER_STATE, "SetInternalScreenDisplayPower, state=%{public}u, reason=%{public}u", state, reason);
259     Rosen::ScreenPowerState status = Rosen::ScreenPowerState::INVALID_STATE;
260     switch (state) {
261         case DisplayState::DISPLAY_ON:
262             status = Rosen::ScreenPowerState::POWER_ON;
263             break;
264         case DisplayState::DISPLAY_OFF:
265             status = Rosen::ScreenPowerState::POWER_OFF;
266             break;
267         default:
268             break;
269     }
270 
271     auto dmsReason = PowerUtils::GetDmsReasonByPowerReason(reason);
272     uint64_t screenId = Rosen::DisplayManagerLite::GetInstance().GetInternalScreenId();
273     bool ret = DisplayManagerLite::GetInstance().SetScreenPowerById(screenId, status, dmsReason);
274     POWER_HILOGI(FEATURE_POWER_STATE,
275         "SetInternalScreenDisplayPower, state=%{public}u, reason=%{public}u, ret = %{public}d", state, reason, ret);
276 }
277 
SetInternalScreenBrightness()278 void DeviceStateAction::SetInternalScreenBrightness()
279 {
280     POWER_HILOGI(FEATURE_POWER_STATE, "SetInternalScreenBrightness");
281     DisplayPowerMgrClient::GetInstance().SetScreenOnBrightness();
282 }
283 
SetCoordinated(bool coordinated)284 void DeviceStateAction::SetCoordinated(bool coordinated)
285 {
286     coordinated_ = coordinated;
287     bool ret = DisplayPowerMgrClient::GetInstance().SetCoordinated(coordinated_);
288     POWER_HILOGI(FEATURE_POWER_STATE, "Set coordinated=%{public}d, ret=%{public}d", coordinated_, ret);
289 }
290 
GoToSleep(const std::function<void ()> onSuspend,const std::function<void ()> onWakeup,bool force)291 uint32_t DeviceStateAction::GoToSleep(const std::function<void()> onSuspend,
292     const std::function<void()> onWakeup, bool force)
293 {
294     SystemSuspendController::GetInstance().Suspend(onSuspend, onWakeup, force);
295     return ActionResult::SUCCESS;
296 }
297 
RegisterCallback(std::function<void (uint32_t)> & callback)298 void DeviceStateAction::RegisterCallback(std::function<void(uint32_t)>& callback)
299 {
300     actionCallback_ = callback;
301 }
302 
OnDisplayStateChanged(uint32_t displayId,DisplayPowerMgr::DisplayState state,uint32_t reason)303 void DeviceStateAction::DisplayPowerCallback::OnDisplayStateChanged(uint32_t displayId,
304     DisplayPowerMgr::DisplayState state, uint32_t reason)
305 {
306     POWER_HILOGD(FEATURE_POWER_STATE, "Callback: OnDisplayStateChanged");
307     int32_t mainDisp = DisplayPowerMgrClient::GetInstance().GetMainDisplayId();
308     if (mainDisp < 0 || static_cast<uint32_t>(mainDisp) != displayId) {
309         POWER_HILOGI(FEATURE_POWER_STATE, "[UL_POWER] It's not main display, skip!");
310         return;
311     }
312     switch (state) {
313         case DisplayPowerMgr::DisplayState::DISPLAY_ON: {
314             std::string identity = IPCSkeleton::ResetCallingIdentity();
315             DisplayManagerLite::GetInstance().WakeUpEnd();
316             IPCSkeleton::SetCallingIdentity(identity);
317             NotifyDisplayActionDone(DISPLAY_ON_DONE);
318             break;
319         }
320         case DisplayPowerMgr::DisplayState::DISPLAY_OFF: {
321             std::string identity = IPCSkeleton::ResetCallingIdentity();
322             DisplayManagerLite::GetInstance().SuspendEnd();
323             IPCSkeleton::SetCallingIdentity(identity);
324             NotifyDisplayActionDone(DISPLAY_OFF_DONE);
325             break;
326         }
327         default:
328             break;
329     }
330     return;
331 }
332 
NotifyDisplayActionDone(uint32_t event)333 void DeviceStateAction::DisplayPowerCallback::NotifyDisplayActionDone(uint32_t event)
334 {
335     std::lock_guard lock(notifyMutex_);
336     if (notify_ != nullptr) {
337         notify_(event);
338     }
339 }
340 } // namespace PowerMgr
341 } // namespace OHOS
342