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 #include "fold_screen_controller/single_display_fold_policy.h"
16 #include <hisysevent.h>
17 #include <hitrace_meter.h>
18 #include <transaction/rs_interfaces.h>
19 #include "session/screen/include/screen_session.h"
20 #include "screen_session_manager.h"
21
22 #include "window_manager_hilog.h"
23
24 #ifdef POWER_MANAGER_ENABLE
25 #include <power_mgr_client.h>
26 #endif
27
28 namespace OHOS::Rosen {
29 namespace {
30 const ScreenId SCREEN_ID_FULL = 0;
31 const ScreenId SCREEN_ID_MAIN = 5;
32
33 #ifdef TP_FEATURE_ENABLE
34 const int32_t TP_TYPE = 12;
35 const int32_t TP_TYPE_POWER_CTRL = 18;
36 const std::string FULL_TP = "0";
37 const std::string MAIN_TP = "1";
38 const std::string MAIN_TP_OFF = "1,1";
39 const std::string FULL_TP_OFF = "0,1";
40 #endif
41 } // namespace
42
SingleDisplayFoldPolicy(std::recursive_mutex & displayInfoMutex,std::shared_ptr<TaskScheduler> screenPowerTaskScheduler)43 SingleDisplayFoldPolicy::SingleDisplayFoldPolicy(std::recursive_mutex& displayInfoMutex,
44 std::shared_ptr<TaskScheduler> screenPowerTaskScheduler)
45 : displayInfoMutex_(displayInfoMutex), screenPowerTaskScheduler_(screenPowerTaskScheduler)
46 {
47 TLOGI(WmsLogTag::DMS, "SingleDisplayFoldPolicy created");
48
49 ScreenId screenIdFull = 0;
50 int32_t foldCreaseRegionPosX = 0;
51 int32_t foldCreaseRegionPosY = 1064;
52 int32_t foldCreaseRegionPosWidth = 2496;
53 int32_t foldCreaseRegionPosHeight = 171;
54
55 std::vector<DMRect> rect = {
56 {
57 foldCreaseRegionPosX, foldCreaseRegionPosY,
58 foldCreaseRegionPosWidth, foldCreaseRegionPosHeight
59 }
60 };
61 currentFoldCreaseRegion_ = new FoldCreaseRegion(screenIdFull, rect);
62 }
63
SetdisplayModeChangeStatus(bool status)64 void SingleDisplayFoldPolicy::SetdisplayModeChangeStatus(bool status)
65 {
66 if (status) {
67 pengdingTask_ = FOLD_TO_EXPAND_TASK_NUM;
68 startTimePoint_ = std::chrono::steady_clock::now();
69 displayModeChangeRunning_ = status;
70 } else {
71 pengdingTask_ --;
72 if (pengdingTask_ != 0) {
73 return;
74 }
75 displayModeChangeRunning_ = false;
76 endTimePoint_ = std::chrono::steady_clock::now();
77 if (lastCachedisplayMode_.load() != GetScreenDisplayMode()) {
78 ScreenSessionManager::GetInstance().TriggerDisplayModeUpdate(lastCachedisplayMode_.load());
79 }
80 }
81 }
82
ChangeScreenDisplayMode(FoldDisplayMode displayMode,DisplayModeChangeReason reason)83 void SingleDisplayFoldPolicy::ChangeScreenDisplayMode(FoldDisplayMode displayMode, DisplayModeChangeReason reason)
84 {
85 SetLastCacheDisplayMode(displayMode);
86 if (GetModeChangeRunningStatus()) {
87 TLOGW(WmsLogTag::DMS, "last process not complete, skip mode: %{public}d", displayMode);
88 return;
89 }
90 TLOGI(WmsLogTag::DMS, "start change displaymode: %{public}d, lastElapsedMs: %{public}" PRId64 "ms",
91 displayMode, getFoldingElapsedMs());
92
93 sptr<ScreenSession> screenSession = ScreenSessionManager::GetInstance().GetScreenSession(SCREEN_ID_FULL);
94 if (screenSession == nullptr) {
95 TLOGE(WmsLogTag::DMS, "default screenSession is null");
96 return;
97 }
98
99 HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "ssm:ChangeScreenDisplayMode(displayMode = %" PRIu64")", displayMode);
100 {
101 std::lock_guard<std::recursive_mutex> lock_mode(displayModeMutex_);
102 if (currentDisplayMode_ == displayMode) {
103 TLOGW(WmsLogTag::DMS, "ChangeScreenDisplayMode already in displayMode %{public}d", displayMode);
104 return;
105 }
106 }
107 SetdisplayModeChangeStatus(true);
108 ReportFoldDisplayModeChange(displayMode);
109 switch (displayMode) {
110 case FoldDisplayMode::MAIN: {
111 ChangeScreenDisplayModeToMain(screenSession, reason);
112 break;
113 }
114 case FoldDisplayMode::FULL: {
115 ChangeScreenDisplayModeToFull(screenSession, reason);
116 break;
117 }
118 case FoldDisplayMode::UNKNOWN: {
119 TLOGI(WmsLogTag::DMS, "ChangeScreenDisplayMode displayMode is unknown");
120 break;
121 }
122 default: {
123 TLOGI(WmsLogTag::DMS, "ChangeScreenDisplayMode displayMode is invalid");
124 break;
125 }
126 }
127 {
128 std::lock_guard<std::recursive_mutex> lock_mode(displayModeMutex_);
129 currentDisplayMode_ = displayMode;
130 lastDisplayMode_ = displayMode;
131 }
132 ScreenSessionManager::GetInstance().NotifyDisplayModeChanged(displayMode);
133 }
134
SendSensorResult(FoldStatus foldStatus)135 void SingleDisplayFoldPolicy::SendSensorResult(FoldStatus foldStatus)
136 {
137 TLOGI(WmsLogTag::DMS, "SendSensorResult FoldStatus: %{public}d", foldStatus);
138 FoldDisplayMode displayMode = GetModeMatchStatus();
139 ChangeScreenDisplayMode(displayMode);
140 }
141
GetCurrentFoldCreaseRegion()142 sptr<FoldCreaseRegion> SingleDisplayFoldPolicy::GetCurrentFoldCreaseRegion()
143 {
144 TLOGI(WmsLogTag::DMS, "GetCurrentFoldCreaseRegion");
145 return currentFoldCreaseRegion_;
146 }
147
LockDisplayStatus(bool locked)148 void SingleDisplayFoldPolicy::LockDisplayStatus(bool locked)
149 {
150 TLOGI(WmsLogTag::DMS, "LockDisplayStatus locked: %{public}d", locked);
151 lockDisplayStatus_ = locked;
152 }
153
SetOnBootAnimation(bool onBootAnimation)154 void SingleDisplayFoldPolicy::SetOnBootAnimation(bool onBootAnimation)
155 {
156 TLOGI(WmsLogTag::DMS, "SetOnBootAnimation onBootAnimation: %{public}d", onBootAnimation);
157 onBootAnimation_ = onBootAnimation;
158 if (!onBootAnimation_) {
159 TLOGI(WmsLogTag::DMS, "SetOnBootAnimation when boot animation finished, change display mode");
160 RecoverWhenBootAnimationExit();
161 }
162 }
163
RecoverWhenBootAnimationExit()164 void SingleDisplayFoldPolicy::RecoverWhenBootAnimationExit()
165 {
166 TLOGI(WmsLogTag::DMS, "RecoverWhenBootAnimationExit currentScreen(%{public}" PRIu64 ")", screenId_);
167 FoldDisplayMode displayMode = GetModeMatchStatus();
168 if (currentDisplayMode_ != displayMode) {
169 ChangeScreenDisplayMode(displayMode);
170 }
171 }
172
UpdateForPhyScreenPropertyChange()173 void SingleDisplayFoldPolicy::UpdateForPhyScreenPropertyChange()
174 {
175 TLOGI(WmsLogTag::DMS, "UpdateForPhyScreenPropertyChange currentScreen(%{public}" PRIu64 ")", screenId_);
176 FoldDisplayMode displayMode = GetModeMatchStatus();
177 if (currentDisplayMode_ != displayMode) {
178 ChangeScreenDisplayMode(displayMode);
179 }
180 }
181
GetModeMatchStatus()182 FoldDisplayMode SingleDisplayFoldPolicy::GetModeMatchStatus()
183 {
184 FoldDisplayMode displayMode = FoldDisplayMode::UNKNOWN;
185 switch (currentFoldStatus_) {
186 case FoldStatus::EXPAND: {
187 displayMode = FoldDisplayMode::FULL;
188 break;
189 }
190 case FoldStatus::FOLDED: {
191 displayMode = FoldDisplayMode::MAIN;
192 break;
193 }
194 case FoldStatus::HALF_FOLD: {
195 displayMode = FoldDisplayMode::FULL;
196 break;
197 }
198 default: {
199 TLOGI(WmsLogTag::DMS, "GetModeMatchStatus FoldStatus is invalid");
200 }
201 }
202 return displayMode;
203 }
204
ReportFoldDisplayModeChange(FoldDisplayMode displayMode)205 void SingleDisplayFoldPolicy::ReportFoldDisplayModeChange(FoldDisplayMode displayMode)
206 {
207 int32_t mode = static_cast<int32_t>(displayMode);
208 TLOGI(WmsLogTag::DMS, "ReportFoldDisplayModeChange displayMode: %{public}d", mode);
209 int32_t ret = HiSysEventWrite(
210 OHOS::HiviewDFX::HiSysEvent::Domain::WINDOW_MANAGER,
211 "DISPLAY_MODE",
212 OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR,
213 "FOLD_DISPLAY_MODE", mode);
214 if (ret != 0) {
215 TLOGE(WmsLogTag::DMS, "ReportFoldDisplayModeChange Write HiSysEvent error, ret: %{public}d", ret);
216 }
217 }
218
ReportFoldStatusChangeBegin(int32_t offScreen,int32_t onScreen)219 void SingleDisplayFoldPolicy::ReportFoldStatusChangeBegin(int32_t offScreen, int32_t onScreen)
220 {
221 TLOGI(WmsLogTag::DMS, "ReportFoldStatusChangeBegin offScreen: %{public}d, onScreen: %{public}d",
222 offScreen, onScreen);
223 int32_t ret = HiSysEventWrite(
224 OHOS::HiviewDFX::HiSysEvent::Domain::WINDOW_MANAGER,
225 "FOLD_STATE_CHANGE_BEGIN",
226 OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR,
227 "POWER_OFF_SCREEN", offScreen,
228 "POWER_ON_SCREEN", onScreen);
229 if (ret != 0) {
230 TLOGE(WmsLogTag::DMS, "ReportFoldStatusChangeBegin Write HiSysEvent error, ret: %{public}d", ret);
231 }
232 }
233
ChangeScreenDisplayModeToMain(sptr<ScreenSession> screenSession,DisplayModeChangeReason reason)234 void SingleDisplayFoldPolicy::ChangeScreenDisplayModeToMain(sptr<ScreenSession> screenSession,
235 DisplayModeChangeReason reason)
236 {
237 if (onBootAnimation_) {
238 ChangeScreenDisplayModeToMainOnBootAnimation(screenSession);
239 return;
240 }
241 #ifdef TP_FEATURE_ENABLE
242 RSInterfaces::GetInstance().SetTpFeatureConfig(TP_TYPE, MAIN_TP.c_str());
243 #endif
244 if (PowerMgr::PowerMgrClient::GetInstance().IsFoldScreenOn()) {
245 TLOGI(WmsLogTag::DMS, "IsFoldScreenOn is true, begin.");
246 ReportFoldStatusChangeBegin((int32_t)SCREEN_ID_FULL, (int32_t)SCREEN_ID_MAIN);
247 auto taskScreenOnMain = [=] {
248 // off full screen
249 TLOGI(WmsLogTag::DMS, "ChangeScreenDisplayModeToMain: IsFoldScreenOn is true, screenIdFull OFF.");
250 screenId_ = SCREEN_ID_FULL;
251 ChangeScreenDisplayModePower(ScreenPowerStatus::POWER_STATUS_OFF);
252 SetdisplayModeChangeStatus(false);
253
254 // on main screen
255 TLOGI(WmsLogTag::DMS, "ChangeScreenDisplayModeToMain: IsFoldScreenOn is true, screenIdMain ON.");
256 screenId_ = SCREEN_ID_MAIN;
257 ChangeScreenDisplayModePower(ScreenPowerStatus::POWER_STATUS_ON);
258 SetdisplayModeChangeStatus(false);
259 };
260 screenPowerTaskScheduler_->PostAsyncTask(taskScreenOnMain, "screenOnMainTask");
261 SendPropertyChangeResult(screenSession, SCREEN_ID_MAIN, ScreenPropertyChangeReason::FOLD_SCREEN_FOLDING);
262 } else { // When the screen is off and folded, it is not powered on
263 TLOGI(WmsLogTag::DMS, "IsFoldScreenOn is false, begin.");
264 // off full screen
265 auto taskScreenOffMainOff = [=] {
266 TLOGI(WmsLogTag::DMS, "ChangeScreenDisplayModeToMain: IsFoldScreenOn is false, screenIdFull OFF.");
267 screenId_ = SCREEN_ID_FULL;
268 ChangeScreenDisplayModePower(ScreenPowerStatus::POWER_STATUS_OFF);
269 SetdisplayModeChangeStatus(false);
270 };
271 screenPowerTaskScheduler_->PostAsyncTask(taskScreenOffMainOff, "screenOffMainOffTask");
272 SendPropertyChangeResult(screenSession, SCREEN_ID_MAIN, ScreenPropertyChangeReason::FOLD_SCREEN_FOLDING);
273 auto taskScreenOnMainChangeScreenId = [=] {
274 TLOGI(WmsLogTag::DMS, "ChangeScreenDisplayModeToMain: IsFoldScreenOn is false, Change ScreenId to Main.");
275 screenId_ = SCREEN_ID_MAIN;
276 #ifdef TP_FEATURE_ENABLE
277 RSInterfaces::GetInstance().SetTpFeatureConfig(TP_TYPE_POWER_CTRL, MAIN_TP_OFF.c_str());
278 #endif
279 SetdisplayModeChangeStatus(false);
280 };
281 screenPowerTaskScheduler_->PostAsyncTask(taskScreenOnMainChangeScreenId, "taskScreenOnMainChangeScreenId");
282 }
283 }
284
ChangeScreenDisplayModeToFull(sptr<ScreenSession> screenSession,DisplayModeChangeReason reason)285 void SingleDisplayFoldPolicy::ChangeScreenDisplayModeToFull(sptr<ScreenSession> screenSession,
286 DisplayModeChangeReason reason)
287 {
288 if (onBootAnimation_) {
289 ChangeScreenDisplayModeToFullOnBootAnimation(screenSession);
290 return;
291 }
292 ReportFoldStatusChangeBegin((int32_t)SCREEN_ID_MAIN, (int32_t)SCREEN_ID_FULL);
293 #ifdef TP_FEATURE_ENABLE
294 RSInterfaces::GetInstance().SetTpFeatureConfig(TP_TYPE, FULL_TP.c_str());
295 #endif
296 if (PowerMgr::PowerMgrClient::GetInstance().IsFoldScreenOn()) {
297 TLOGI(WmsLogTag::DMS, "IsFoldScreenOn is true, begin.");
298 auto taskScreenOnFull = [=] {
299 // off main screen
300 TLOGI(WmsLogTag::DMS, "ChangeScreenDisplayModeToFull: IsFoldScreenOn is true, screenIdMain OFF.");
301 screenId_ = SCREEN_ID_MAIN;
302 ChangeScreenDisplayModePower(ScreenPowerStatus::POWER_STATUS_OFF);
303 SetdisplayModeChangeStatus(false);
304
305 // on full screen
306 TLOGI(WmsLogTag::DMS, "ChangeScreenDisplayModeToFull: IsFoldScreenOn is true, screenIdFull ON.");
307 screenId_ = SCREEN_ID_FULL;
308 ChangeScreenDisplayModePower(ScreenPowerStatus::POWER_STATUS_ON);
309 SetdisplayModeChangeStatus(false);
310 };
311 screenPowerTaskScheduler_->PostAsyncTask(taskScreenOnFull, "screenOnFullTask");
312 SendPropertyChangeResult(screenSession, SCREEN_ID_FULL, ScreenPropertyChangeReason::FOLD_SCREEN_EXPAND);
313 } else { //AOD scene
314 TLOGI(WmsLogTag::DMS, "IsFoldScreenOn is false, begin.");
315 // off main screen
316 auto taskScreenOffFullOff = [=] {
317 TLOGI(WmsLogTag::DMS, "ChangeScreenDisplayModeToFull: IsFoldScreenOn is false, screenIdMain OFF.");
318 screenId_ = SCREEN_ID_MAIN;
319 ChangeScreenDisplayModePower(ScreenPowerStatus::POWER_STATUS_OFF);
320 SetdisplayModeChangeStatus(false);
321 };
322 screenPowerTaskScheduler_->PostAsyncTask(taskScreenOffFullOff, "screenOffFullOffTask");
323 SendPropertyChangeResult(screenSession, SCREEN_ID_FULL, ScreenPropertyChangeReason::FOLD_SCREEN_EXPAND);
324 // on full screen
325 auto taskScreenOnFullOn = [=] {
326 TLOGI(WmsLogTag::DMS, "ChangeScreenDisplayModeToFull: IsFoldScreenOn is false, screenIdFull ON.");
327 screenId_ = SCREEN_ID_FULL;
328 if (reason == DisplayModeChangeReason::RECOVER) {
329 #ifdef TP_FEATURE_ENABLE
330 RSInterfaces::GetInstance().SetTpFeatureConfig(TP_TYPE_POWER_CTRL, FULL_TP_OFF.c_str());
331 #endif
332 } else {
333 PowerMgr::PowerMgrClient::GetInstance().WakeupDeviceAsync();
334 }
335 SetdisplayModeChangeStatus(false);
336 };
337 screenPowerTaskScheduler_->PostAsyncTask(taskScreenOnFullOn, "screenOnFullOnTask");
338 }
339 }
340
ChangeScreenDisplayModePower(ScreenPowerStatus screenPowerStatus)341 void SingleDisplayFoldPolicy::ChangeScreenDisplayModePower(ScreenPowerStatus screenPowerStatus)
342 {
343 ScreenSessionManager::GetInstance().SetKeyguardDrawnDoneFlag(false);
344 ScreenSessionManager::GetInstance().SetScreenPowerForFold(screenPowerStatus);
345 }
346
SendPropertyChangeResult(sptr<ScreenSession> screenSession,ScreenId screenId,ScreenPropertyChangeReason reason)347 void SingleDisplayFoldPolicy::SendPropertyChangeResult(sptr<ScreenSession> screenSession, ScreenId screenId,
348 ScreenPropertyChangeReason reason)
349 {
350 std::lock_guard<std::recursive_mutex> lock_info(displayInfoMutex_);
351 screenProperty_ = ScreenSessionManager::GetInstance().GetPhyScreenProperty(screenId);
352 screenSession->UpdatePropertyByFoldControl(screenProperty_);
353 screenSession->PropertyChange(screenSession->GetScreenProperty(), reason);
354 screenSession->SetRotationAndScreenRotationOnly(Rotation::ROTATION_0);
355 TLOGI(WmsLogTag::DMS, "screenBounds : width_= %{public}f, height_= %{public}f",
356 screenSession->GetScreenProperty().GetBounds().rect_.width_,
357 screenSession->GetScreenProperty().GetBounds().rect_.height_);
358 ScreenSessionManager::GetInstance().NotifyDisplayChanged(screenSession->ConvertToDisplayInfo(),
359 DisplayChangeEvent::DISPLAY_SIZE_CHANGED);
360 }
361
ChangeScreenDisplayModeToMainOnBootAnimation(sptr<ScreenSession> screenSession)362 void SingleDisplayFoldPolicy::ChangeScreenDisplayModeToMainOnBootAnimation(sptr<ScreenSession> screenSession)
363 {
364 TLOGI(WmsLogTag::DMS, "ChangeScreenDisplayModeToMainOnBootAnimation");
365 screenProperty_ = ScreenSessionManager::GetInstance().GetPhyScreenProperty(SCREEN_ID_MAIN);
366 screenSession->UpdatePropertyByFoldControl(screenProperty_);
367 screenSession->PropertyChange(screenSession->GetScreenProperty(),
368 ScreenPropertyChangeReason::FOLD_SCREEN_FOLDING);
369 TLOGI(WmsLogTag::DMS, "screenBounds : width_= %{public}f, height_= %{public}f",
370 screenSession->GetScreenProperty().GetBounds().rect_.width_,
371 screenSession->GetScreenProperty().GetBounds().rect_.height_);
372 screenId_ = SCREEN_ID_MAIN;
373 }
374
ChangeScreenDisplayModeToFullOnBootAnimation(sptr<ScreenSession> screenSession)375 void SingleDisplayFoldPolicy::ChangeScreenDisplayModeToFullOnBootAnimation(sptr<ScreenSession> screenSession)
376 {
377 TLOGI(WmsLogTag::DMS, "ChangeScreenDisplayModeToFullOnBootAnimation");
378 screenProperty_ = ScreenSessionManager::GetInstance().GetPhyScreenProperty(SCREEN_ID_FULL);
379 screenSession->UpdatePropertyByFoldControl(screenProperty_);
380 screenSession->PropertyChange(screenSession->GetScreenProperty(),
381 ScreenPropertyChangeReason::FOLD_SCREEN_EXPAND);
382 TLOGI(WmsLogTag::DMS, "screenBounds : width_= %{public}f, height_= %{public}f",
383 screenSession->GetScreenProperty().GetBounds().rect_.width_,
384 screenSession->GetScreenProperty().GetBounds().rect_.height_);
385 screenId_ = SCREEN_ID_FULL;
386 }
387 } // namespace OHOS::Rosen