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 <hisysevent.h>
17 #include <hitrace_meter.h>
18 #include <parameters.h>
19 #include <transaction/rs_interfaces.h>
20 #include "fold_screen_controller/single_display_pocket_fold_policy.h"
21 #include "rs_adapter.h"
22 #include "session/screen/include/screen_session.h"
23 #include "screen_session_manager.h"
24 #include "fold_screen_state_internel.h"
25
26 #include "window_manager_hilog.h"
27
28 #ifdef POWER_MANAGER_ENABLE
29 #include <power_mgr_client.h>
30 #endif
31 #ifdef POWERMGR_DISPLAY_MANAGER_ENABLE
32 #include <display_power_mgr_client.h>
33 #endif
34
35 namespace OHOS::Rosen {
36 namespace {
37 const ScreenId SCREEN_ID_FULL = 0;
38 const ScreenId SCREEN_ID_MAIN = 5;
39
40 const int32_t REMOVE_DISPLAY_NODE = 0;
41 const int32_t ADD_DISPLAY_NODE = 1;
42 const std::string g_FoldScreenRect = system::GetParameter("const.display.foldscreen.crease_region", "");
43 const std::string FOLD_CREASE_DELIMITER = ",;";
44 constexpr int32_t FOLD_CREASE_RECT_SIZE = 4; //numbers of parameter on the current device is 4
45
46 #ifdef TP_FEATURE_ENABLE
47 const int32_t TP_TYPE = 12;
48 const int32_t TP_TYPE_POWER_CTRL = 18;
49 const std::string FULL_TP = "0";
50 const std::string MAIN_TP = "1";
51 const std::string MAIN_TP_OFF = "1,1";
52 const std::string FULL_TP_OFF = "0.1";
53 #endif
54 } // namespace
55
SingleDisplayPocketFoldPolicy(std::recursive_mutex & displayInfoMutex,std::shared_ptr<TaskScheduler> screenPowerTaskScheduler)56 SingleDisplayPocketFoldPolicy::SingleDisplayPocketFoldPolicy(std::recursive_mutex& displayInfoMutex,
57 std::shared_ptr<TaskScheduler> screenPowerTaskScheduler)
58 : displayInfoMutex_(displayInfoMutex), screenPowerTaskScheduler_(screenPowerTaskScheduler)
59 {
60 TLOGI(WmsLogTag::DMS, "SingleDisplayPocketFoldPolicy created");
61
62 ScreenId screenIdFull = 0;
63 int32_t foldCreaseRegionPosX = 0;
64 int32_t foldCreaseRegionPosY = 1064;
65 int32_t foldCreaseRegionPosWidth = 2496;
66 int32_t foldCreaseRegionPosHeight = 171;
67
68 std::vector<DMRect> rect = {
69 {
70 foldCreaseRegionPosX, foldCreaseRegionPosY,
71 foldCreaseRegionPosWidth, foldCreaseRegionPosHeight
72 }
73 };
74 currentFoldCreaseRegion_ = new FoldCreaseRegion(screenIdFull, rect);
75 }
76
GetFoldCreaseRegion(bool isVertical) const77 FoldCreaseRegion SingleDisplayPocketFoldPolicy::GetFoldCreaseRegion(bool isVertical) const
78 {
79 std::vector<int32_t> foldRect = FoldScreenStateInternel::StringFoldRectSplitToInt(g_FoldScreenRect,
80 FOLD_CREASE_DELIMITER);
81 if (foldRect.size() != FOLD_CREASE_RECT_SIZE) {
82 TLOGE(WmsLogTag::DMS, "foldRect is invalid");
83 return FoldCreaseRegion(0, {});
84 }
85
86 ScreenId screenIdFull = 0;
87 std::vector<DMRect> foldCreaseRect;
88 GetFoldCreaseRect(isVertical, foldRect, foldCreaseRect);
89 return FoldCreaseRegion(screenIdFull, foldCreaseRect);
90 }
91
GetFoldCreaseRect(bool isVertical,const std::vector<int32_t> & foldRect,std::vector<DMRect> & foldCreaseRect) const92 void SingleDisplayPocketFoldPolicy::GetFoldCreaseRect(bool isVertical,
93 const std::vector<int32_t>& foldRect, std::vector<DMRect>& foldCreaseRect) const
94 {
95 int32_t liveCreaseRegionPosX; // live Crease Region PosX
96 int32_t liveCreaseRegionPosY; // live Crease Region PosY
97 uint32_t liveCreaseRegionPosWidth; // live Crease Region PosWidth
98 uint32_t liveCreaseRegionPosHeight; // live Crease Region PosHeight
99 if (isVertical) {
100 TLOGI(WmsLogTag::DMS, "the current FoldCreaseRect is vertical");
101 liveCreaseRegionPosX = foldRect[1];
102 liveCreaseRegionPosY = foldRect[0];
103 liveCreaseRegionPosWidth = static_cast<uint32_t>(foldRect[3]);
104 liveCreaseRegionPosHeight = static_cast<uint32_t>(foldRect[2]);
105 } else {
106 TLOGI(WmsLogTag::DMS, "the current FoldCreaseRect is horizontal");
107 liveCreaseRegionPosX = foldRect[0];
108 liveCreaseRegionPosY = foldRect[1];
109 liveCreaseRegionPosWidth = static_cast<uint32_t>(foldRect[2]);
110 liveCreaseRegionPosHeight = static_cast<uint32_t>(foldRect[3]);
111 }
112 foldCreaseRect = {
113 {
114 liveCreaseRegionPosX, liveCreaseRegionPosY,
115 liveCreaseRegionPosWidth, liveCreaseRegionPosHeight
116 }
117 };
118 return;
119 }
120
SetdisplayModeChangeStatus(bool status,bool isOnBootAnimation)121 void SingleDisplayPocketFoldPolicy::SetdisplayModeChangeStatus(bool status, bool isOnBootAnimation)
122 {
123 if (status) {
124 pengdingTask_ = isOnBootAnimation ? FOLD_TO_EXPAND_ONBOOTANIMATION_TASK_NUM : FOLD_TO_EXPAND_TASK_NUM;
125 startTimePoint_ = std::chrono::steady_clock::now();
126 SetIsFirstFrameCommitReported(false);
127 displayModeChangeRunning_ = status;
128 TLOGI(WmsLogTag::DMS, "displaymodechange start, taskCount: %{public}d", pengdingTask_.load());
129 } else {
130 pengdingTask_ --;
131 if (pengdingTask_ != 0) {
132 TLOGI(WmsLogTag::DMS, "displaymodechange 1 task finished, %{public}d task(s) left", pengdingTask_.load());
133 return;
134 }
135 displayModeChangeRunning_ = false;
136 endTimePoint_ = std::chrono::steady_clock::now();
137 TLOGI(WmsLogTag::DMS, "displaymodechange finished, current displaymode: %{public}ud,"
138 "target displaymode: %{public}ud", GetScreenDisplayMode(), lastCachedisplayMode_.load());
139 if (lastCachedisplayMode_.load() != GetScreenDisplayMode()) {
140 ScreenSessionManager::GetInstance().TriggerDisplayModeUpdate(lastCachedisplayMode_.load());
141 }
142 }
143 }
144
ChangeScreenDisplayMode(FoldDisplayMode displayMode,DisplayModeChangeReason reason)145 void SingleDisplayPocketFoldPolicy::ChangeScreenDisplayMode(FoldDisplayMode displayMode,
146 DisplayModeChangeReason reason)
147 {
148 SetLastCacheDisplayMode(displayMode);
149 if (GetModeChangeRunningStatus()) {
150 TLOGW(WmsLogTag::DMS, "last process not complete, skip mode: %{public}d", displayMode);
151 return;
152 }
153 TLOGI(WmsLogTag::DMS, "start change displaymode: %{public}d, lastElapsedMs: %{public}" PRId64 "ms",
154 displayMode, getFoldingElapsedMs());
155
156 sptr<ScreenSession> screenSession = ScreenSessionManager::GetInstance().GetScreenSession(SCREEN_ID_FULL);
157 if (screenSession == nullptr) {
158 TLOGE(WmsLogTag::DMS, "default screenSession is null");
159 return;
160 }
161 HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "ssm:ChangeScreenDisplayMode(displayMode = %" PRIu64")", displayMode);
162 {
163 std::lock_guard<std::recursive_mutex> lock_mode(displayModeMutex_);
164 if (currentDisplayMode_ == displayMode) {
165 TLOGW(WmsLogTag::DMS, "ChangeScreenDisplayMode already in displayMode %{public}d", displayMode);
166 return;
167 }
168 }
169 ReportFoldDisplayModeChange(displayMode);
170 {
171 std::lock_guard<std::recursive_mutex> lock_mode(displayModeMutex_);
172 lastDisplayMode_ = displayMode;
173 }
174 if (!ScreenSessionManager::GetInstance().GetTentMode()) {
175 if (displayMode == FoldDisplayMode::MAIN) {
176 TLOGI(WmsLogTag::DMS, "Set device status to STATUS_FOLDED");
177 SetDeviceStatus(static_cast<uint32_t>(DMDeviceStatus::STATUS_FOLDED));
178 system::SetParameter("persist.dms.device.status",
179 std::to_string(static_cast<uint32_t>(DMDeviceStatus::STATUS_FOLDED)));
180 } else {
181 TLOGI(WmsLogTag::DMS, "Set device status to UNKNOWN");
182 SetDeviceStatus(static_cast<uint32_t>(DMDeviceStatus::UNKNOWN));
183 system::SetParameter("persist.dms.device.status",
184 std::to_string(static_cast<uint32_t>(DMDeviceStatus::UNKNOWN)));
185 }
186 }
187 ChangeScreenDisplayModeProc(screenSession, displayMode, reason);
188 {
189 std::lock_guard<std::recursive_mutex> lock_mode(displayModeMutex_);
190 currentDisplayMode_ = displayMode;
191 }
192 ScreenSessionManager::GetInstance().NotifyDisplayModeChanged(displayMode);
193 ScreenSessionManager::GetInstance().SwitchScrollParam(displayMode);
194 }
195
ChangeScreenDisplayModeProc(sptr<ScreenSession> screenSession,FoldDisplayMode displayMode,DisplayModeChangeReason reason)196 void SingleDisplayPocketFoldPolicy::ChangeScreenDisplayModeProc(sptr<ScreenSession> screenSession,
197 FoldDisplayMode displayMode, DisplayModeChangeReason reason)
198 {
199 switch (displayMode) {
200 case FoldDisplayMode::MAIN: {
201 if (currentDisplayMode_ == FoldDisplayMode::COORDINATION) {
202 CloseCoordinationScreen();
203 }
204 ChangeScreenDisplayModeToMain(screenSession);
205 break;
206 }
207 case FoldDisplayMode::FULL: {
208 if (currentDisplayMode_ == FoldDisplayMode::COORDINATION) {
209 CloseCoordinationScreen();
210 } else {
211 ChangeScreenDisplayModeToFull(screenSession, reason);
212 }
213 break;
214 }
215 case FoldDisplayMode::COORDINATION: {
216 ChangeScreenDisplayModeToCoordination();
217 break;
218 }
219 case FoldDisplayMode::UNKNOWN: {
220 TLOGI(WmsLogTag::DMS, "displayMode is unknown");
221 break;
222 }
223 default: {
224 TLOGI(WmsLogTag::DMS, "displayMode is invalid");
225 break;
226 }
227 }
228 }
229
SendSensorResult(FoldStatus foldStatus)230 void SingleDisplayPocketFoldPolicy::SendSensorResult(FoldStatus foldStatus)
231 {
232 TLOGI(WmsLogTag::DMS, "SendSensorResult FoldStatus: %{public}d", foldStatus);
233 FoldDisplayMode displayMode = GetModeMatchStatus();
234 if (!(currentDisplayMode_ == FoldDisplayMode::COORDINATION &&
235 displayMode == FoldDisplayMode::FULL)) {
236 ChangeScreenDisplayMode(displayMode);
237 }
238 }
239
GetCurrentFoldCreaseRegion()240 sptr<FoldCreaseRegion> SingleDisplayPocketFoldPolicy::GetCurrentFoldCreaseRegion()
241 {
242 TLOGI(WmsLogTag::DMS, "GetCurrentFoldCreaseRegion");
243 return currentFoldCreaseRegion_;
244 }
245
GetLiveCreaseRegion()246 FoldCreaseRegion SingleDisplayPocketFoldPolicy::GetLiveCreaseRegion()
247 {
248 TLOGI(WmsLogTag::DMS, "enter");
249 std::lock_guard<std::mutex> lock_mode(liveCreaseRegionMutex_);
250 FoldDisplayMode displayMode = GetScreenDisplayMode();
251 if (displayMode == FoldDisplayMode::UNKNOWN || displayMode == FoldDisplayMode::MAIN) {
252 return FoldCreaseRegion(0, {});
253 }
254 sptr<ScreenSession> screenSession = ScreenSessionManager::GetInstance().GetScreenSession(SCREEN_ID_FULL);
255 if (screenSession == nullptr) {
256 TLOGE(WmsLogTag::DMS, "default screenSession is null");
257 return FoldCreaseRegion(0, {});
258 }
259 DisplayOrientation displayOrientation = screenSession->GetScreenProperty().GetDisplayOrientation();
260 if (displayMode == FoldDisplayMode::FULL || displayMode == FoldDisplayMode::COORDINATION) {
261 switch (displayOrientation) {
262 case DisplayOrientation::PORTRAIT:
263 case DisplayOrientation::PORTRAIT_INVERTED: {
264 liveCreaseRegion_ = GetFoldCreaseRegion(false);
265 break;
266 }
267 case DisplayOrientation::LANDSCAPE:
268 case DisplayOrientation::LANDSCAPE_INVERTED: {
269 liveCreaseRegion_ = GetFoldCreaseRegion(true);
270 break;
271 }
272 default: {
273 TLOGE(WmsLogTag::DMS, "displayOrientation is invalid");
274 }
275 }
276 }
277 return liveCreaseRegion_;
278 }
279
LockDisplayStatus(bool locked)280 void SingleDisplayPocketFoldPolicy::LockDisplayStatus(bool locked)
281 {
282 TLOGI(WmsLogTag::DMS, "LockDisplayStatus locked: %{public}d", locked);
283 lockDisplayStatus_ = locked;
284 }
285
SetOnBootAnimation(bool onBootAnimation)286 void SingleDisplayPocketFoldPolicy::SetOnBootAnimation(bool onBootAnimation)
287 {
288 TLOGI(WmsLogTag::DMS, "onBootAnimation: %{public}d", onBootAnimation);
289 onBootAnimation_ = onBootAnimation;
290 if (!onBootAnimation_) {
291 TLOGI(WmsLogTag::DMS, "when boot animation finished, change display mode");
292 RecoverWhenBootAnimationExit();
293 NotifyRefreshRateEvent(false);
294 } else {
295 NotifyRefreshRateEvent(true);
296 }
297 }
298
RecoverWhenBootAnimationExit()299 void SingleDisplayPocketFoldPolicy::RecoverWhenBootAnimationExit()
300 {
301 TLOGI(WmsLogTag::DMS, "CurrentScreen(%{public}" PRIu64 ")", screenId_);
302 FoldDisplayMode displayMode = GetModeMatchStatus();
303 if (currentDisplayMode_ != displayMode) {
304 ChangeScreenDisplayMode(displayMode);
305 }
306 }
307
UpdateForPhyScreenPropertyChange()308 void SingleDisplayPocketFoldPolicy::UpdateForPhyScreenPropertyChange()
309 {
310 TLOGI(WmsLogTag::DMS, "CurrentScreen(%{public}" PRIu64 ")", screenId_);
311 FoldDisplayMode displayMode = GetModeMatchStatus();
312 if (currentDisplayMode_ != displayMode) {
313 ChangeScreenDisplayMode(displayMode);
314 }
315 }
316
GetModeMatchStatus()317 FoldDisplayMode SingleDisplayPocketFoldPolicy::GetModeMatchStatus()
318 {
319 FoldDisplayMode displayMode = FoldDisplayMode::UNKNOWN;
320 switch (currentFoldStatus_) {
321 case FoldStatus::EXPAND: {
322 displayMode = FoldDisplayMode::FULL;
323 break;
324 }
325 case FoldStatus::FOLDED: {
326 displayMode = FoldDisplayMode::MAIN;
327 break;
328 }
329 case FoldStatus::HALF_FOLD: {
330 displayMode = FoldDisplayMode::FULL;
331 break;
332 }
333 default: {
334 TLOGI(WmsLogTag::DMS, "GetModeMatchStatus FoldStatus is invalid");
335 }
336 }
337 return displayMode;
338 }
339
ReportFoldDisplayModeChange(FoldDisplayMode displayMode)340 void SingleDisplayPocketFoldPolicy::ReportFoldDisplayModeChange(FoldDisplayMode displayMode)
341 {
342 int32_t mode = static_cast<int32_t>(displayMode);
343 TLOGI(WmsLogTag::DMS, "displayMode: %{public}d", mode);
344 int32_t ret = HiSysEventWrite(
345 OHOS::HiviewDFX::HiSysEvent::Domain::WINDOW_MANAGER,
346 "DISPLAY_MODE",
347 OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR,
348 "FOLD_DISPLAY_MODE", mode);
349 if (ret != 0) {
350 TLOGE(WmsLogTag::DMS, "Write HiSysEvent error, ret: %{public}d", ret);
351 }
352 }
353
ReportFoldStatusChangeBegin(int32_t offScreen,int32_t onScreen)354 void SingleDisplayPocketFoldPolicy::ReportFoldStatusChangeBegin(int32_t offScreen, int32_t onScreen)
355 {
356 TLOGI(WmsLogTag::DMS, "offScreen: %{public}d, onScreen: %{public}d",
357 offScreen, onScreen);
358 int32_t ret = HiSysEventWrite(
359 OHOS::HiviewDFX::HiSysEvent::Domain::WINDOW_MANAGER,
360 "FOLD_STATE_CHANGE_BEGIN",
361 OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR,
362 "POWER_OFF_SCREEN", offScreen,
363 "POWER_ON_SCREEN", onScreen);
364 if (ret != 0) {
365 TLOGE(WmsLogTag::DMS, "Write HiSysEvent error, ret: %{public}d", ret);
366 }
367 }
368
ChangeScreenDisplayModeToMainWhenFoldScreenOn(sptr<ScreenSession> screenSession)369 void SingleDisplayPocketFoldPolicy::ChangeScreenDisplayModeToMainWhenFoldScreenOn(sptr<ScreenSession> screenSession)
370 {
371 TLOGI(WmsLogTag::DMS, "IsFoldScreenOn is true, begin.");
372 ReportFoldStatusChangeBegin(static_cast<int32_t>(SCREEN_ID_FULL),
373 static_cast<int32_t>(SCREEN_ID_MAIN));
374 auto taskScreenOnMain = [=] {
375 // off full screen
376 TLOGNI(WmsLogTag::DMS, "ChangeScreenDisplayModeToMain: IsFoldScreenOn is true, screenIdFull OFF.");
377 screenId_ = SCREEN_ID_FULL;
378 ChangeScreenDisplayModePower(SCREEN_ID_FULL, ScreenPowerStatus::POWER_STATUS_OFF);
379 SetdisplayModeChangeStatus(false);
380
381 // on main screen
382 TLOGNI(WmsLogTag::DMS, "ChangeScreenDisplayModeToMain: IsFoldScreenOn is true, screenIdMain ON.");
383 screenId_ = SCREEN_ID_MAIN;
384 ChangeScreenDisplayModePower(SCREEN_ID_MAIN, ScreenPowerStatus::POWER_STATUS_ON);
385 SetdisplayModeChangeStatus(false);
386 };
387 screenPowerTaskScheduler_->PostAsyncTask(taskScreenOnMain, "screenOnMainTask");
388 SendPropertyChangeResult(screenSession, SCREEN_ID_MAIN, ScreenPropertyChangeReason::FOLD_SCREEN_FOLDING);
389 }
390
ChangeScreenDisplayModeToMainWhenFoldScreenOff(sptr<ScreenSession> screenSession)391 void SingleDisplayPocketFoldPolicy::ChangeScreenDisplayModeToMainWhenFoldScreenOff(sptr<ScreenSession> screenSession)
392 {
393 TLOGI(WmsLogTag::DMS, "IsFoldScreenOn is false, begin.");
394 // off full screen
395 auto taskScreenOffMainOff = [=] {
396 TLOGNI(WmsLogTag::DMS, "ChangeScreenDisplayModeToMain: IsFoldScreenOn is false, screenIdFull OFF.");
397 screenId_ = SCREEN_ID_FULL;
398 ChangeScreenDisplayModePower(SCREEN_ID_FULL, ScreenPowerStatus::POWER_STATUS_OFF);
399 SetdisplayModeChangeStatus(false);
400 };
401 screenPowerTaskScheduler_->PostAsyncTask(taskScreenOffMainOff, "screenOffMainOffTask");
402 SendPropertyChangeResult(screenSession, SCREEN_ID_MAIN, ScreenPropertyChangeReason::FOLD_SCREEN_FOLDING);
403 bool ifTentMode = ScreenSessionManager::GetInstance().GetTentMode();
404 auto taskScreenOnMainChangeScreenId = [=] {
405 TLOGNI(WmsLogTag::DMS, "ChangeScreenDisplayModeToMain: IsFoldScreenOn is false, Change ScreenId to Main.");
406 screenId_ = SCREEN_ID_MAIN;
407 #ifdef TP_FEATURE_ENABLE
408 RSInterfaces::GetInstance().SetTpFeatureConfig(TP_TYPE_POWER_CTRL, MAIN_TP_OFF.c_str());
409 #endif
410 if (ifTentMode) {
411 PowerMgr::PowerMgrClient::GetInstance().WakeupDeviceAsync(
412 PowerMgr::WakeupDeviceType::WAKEUP_DEVICE_TENT_MODE_CHANGE);
413 } else {
414 SetIsFirstFrameCommitReported(true);
415 }
416 SetdisplayModeChangeStatus(false);
417 };
418 screenPowerTaskScheduler_->PostAsyncTask(taskScreenOnMainChangeScreenId, "taskScreenOnMainChangeScreenId");
419 }
420
421
ChangeScreenDisplayModeToMain(sptr<ScreenSession> screenSession,DisplayModeChangeReason reason)422 void SingleDisplayPocketFoldPolicy::ChangeScreenDisplayModeToMain(sptr<ScreenSession> screenSession,
423 DisplayModeChangeReason reason)
424 {
425 SetdisplayModeChangeStatus(true);
426 if (onBootAnimation_) {
427 SetdisplayModeChangeStatus(true, true);
428 ChangeScreenDisplayModeToMainOnBootAnimation(screenSession);
429 return;
430 }
431 RSInterfaces::GetInstance().NotifyScreenSwitched();
432 #ifdef TP_FEATURE_ENABLE
433 RSInterfaces::GetInstance().SetTpFeatureConfig(TP_TYPE, MAIN_TP.c_str());
434 #endif
435 if (PowerMgr::PowerMgrClient::GetInstance().IsFoldScreenOn() ||
436 ScreenSessionManager::GetInstance().GetCancelSuspendStatus()) {
437 ChangeScreenDisplayModeToMainWhenFoldScreenOn(screenSession);
438 } else { // When the screen is off and folded, it is not powered on
439 ScreenSessionManager::GetInstance().ForceSkipScreenOffAnimation();
440 ChangeScreenDisplayModeToMainWhenFoldScreenOff(screenSession);
441 }
442 }
443
ChangeScreenDisplayModeToFullWhenFoldScreenOn(sptr<ScreenSession> screenSession)444 void SingleDisplayPocketFoldPolicy::ChangeScreenDisplayModeToFullWhenFoldScreenOn(sptr<ScreenSession> screenSession)
445 {
446 TLOGI(WmsLogTag::DMS, "IsFoldScreenOn is true, begin.");
447 auto taskScreenOnFull = [=] {
448 // off main screen
449 TLOGNI(WmsLogTag::DMS, "ChangeScreenDisplayModeToFull: IsFoldScreenOn is true, screenIdMain OFF.");
450 screenId_ = SCREEN_ID_MAIN;
451 ChangeScreenDisplayModePower(SCREEN_ID_MAIN, ScreenPowerStatus::POWER_STATUS_OFF);
452 SetdisplayModeChangeStatus(false);
453
454 // on full screen
455 TLOGNI(WmsLogTag::DMS, "ChangeScreenDisplayModeToFull: IsFoldScreenOn is true, screenIdFull ON.");
456 screenId_ = SCREEN_ID_FULL;
457 ChangeScreenDisplayModePower(SCREEN_ID_FULL, ScreenPowerStatus::POWER_STATUS_ON);
458 SetdisplayModeChangeStatus(false);
459 };
460 screenPowerTaskScheduler_->PostAsyncTask(taskScreenOnFull, "screenOnFullTask");
461 SendPropertyChangeResult(screenSession, SCREEN_ID_FULL, ScreenPropertyChangeReason::FOLD_SCREEN_EXPAND);
462 }
463
ChangeScreenDisplayModeToFullWhenFoldScreenOff(sptr<ScreenSession> screenSession,DisplayModeChangeReason reason)464 void SingleDisplayPocketFoldPolicy::ChangeScreenDisplayModeToFullWhenFoldScreenOff(sptr<ScreenSession> screenSession,
465 DisplayModeChangeReason reason)
466 {
467 TLOGI(WmsLogTag::DMS, "IsFoldScreenOn is false, begin.");
468 // off main screen
469 auto taskScreenOffFullOff = [=] {
470 TLOGNI(WmsLogTag::DMS, "ChangeScreenDisplayModeToFull: IsFoldScreenOn is false, screenIdMain OFF.");
471 screenId_ = SCREEN_ID_MAIN;
472 ChangeScreenDisplayModePower(SCREEN_ID_MAIN, ScreenPowerStatus::POWER_STATUS_OFF);
473 SetdisplayModeChangeStatus(false);
474 };
475 screenPowerTaskScheduler_->PostAsyncTask(taskScreenOffFullOff, "screenOffFullOffTask");
476 SendPropertyChangeResult(screenSession, SCREEN_ID_FULL, ScreenPropertyChangeReason::FOLD_SCREEN_EXPAND);
477 // on full screen
478 auto taskScreenOnFullOn = [=] {
479 TLOGNI(WmsLogTag::DMS, "ChangeScreenDisplayModeToFull: IsFoldScreenOn is false, screenIdFull ON.");
480 screenId_ = SCREEN_ID_FULL;
481 if (reason == DisplayModeChangeReason::RECOVER) {
482 #ifdef TP_FEATURE_ENABLE
483 RSInterfaces::GetInstance().SetTpFeatureConfig(TP_TYPE_POWER_CTRL, FULL_TP_OFF.c_str());
484 #endif
485 } else {
486 PowerMgr::PowerMgrClient::GetInstance().WakeupDeviceAsync();
487 }
488 SetdisplayModeChangeStatus(false);
489 };
490 screenPowerTaskScheduler_->PostAsyncTask(taskScreenOnFullOn, "screenOnFullOnTask");
491 }
492
ChangeScreenDisplayModeToFull(sptr<ScreenSession> screenSession,DisplayModeChangeReason reason)493 void SingleDisplayPocketFoldPolicy::ChangeScreenDisplayModeToFull(sptr<ScreenSession> screenSession,
494 DisplayModeChangeReason reason)
495 {
496 SetdisplayModeChangeStatus(true);
497 if (onBootAnimation_) {
498 SetdisplayModeChangeStatus(true, true);
499 ChangeScreenDisplayModeToFullOnBootAnimation(screenSession);
500 return;
501 }
502 ScreenSessionManager::GetInstance().UpdateCameraBackSelfie(false);
503 RSInterfaces::GetInstance().NotifyScreenSwitched();
504 ReportFoldStatusChangeBegin((int32_t)SCREEN_ID_MAIN, (int32_t)SCREEN_ID_FULL);
505 #ifdef TP_FEATURE_ENABLE
506 RSInterfaces::GetInstance().SetTpFeatureConfig(TP_TYPE, FULL_TP.c_str());
507 #endif
508 if (PowerMgr::PowerMgrClient::GetInstance().IsFoldScreenOn()) {
509 ChangeScreenDisplayModeToFullWhenFoldScreenOn(screenSession);
510 } else { //AOD scene
511 if (ScreenSessionManager::GetInstance().TryToCancelScreenOff()) {
512 ChangeScreenDisplayModeToFullWhenFoldScreenOn(screenSession);
513 } else {
514 ChangeScreenDisplayModeToFullWhenFoldScreenOff(screenSession, reason);
515 }
516 }
517 }
518
ChangeScreenDisplayModePower(ScreenId screenId,ScreenPowerStatus screenPowerStatus)519 void SingleDisplayPocketFoldPolicy::ChangeScreenDisplayModePower(ScreenId screenId, ScreenPowerStatus screenPowerStatus)
520 {
521 ScreenSessionManager::GetInstance().SetKeyguardDrawnDoneFlag(false);
522 ScreenSessionManager::GetInstance().SetScreenPowerForFold(screenId, screenPowerStatus);
523 }
524
SendPropertyChangeResult(sptr<ScreenSession> screenSession,ScreenId screenId,ScreenPropertyChangeReason reason)525 void SingleDisplayPocketFoldPolicy::SendPropertyChangeResult(sptr<ScreenSession> screenSession, ScreenId screenId,
526 ScreenPropertyChangeReason reason)
527 {
528 std::lock_guard<std::recursive_mutex> lock_info(displayInfoMutex_);
529 screenProperty_ = ScreenSessionManager::GetInstance().GetPhyScreenProperty(screenId);
530 ScreenProperty property = screenSession->UpdatePropertyByFoldControl(screenProperty_);
531 ScreenSessionManager::GetInstance().OnBeforeScreenPropertyChange(currentFoldStatus_);
532 screenSession->SetRotationAndScreenRotationOnly(Rotation::ROTATION_0);
533 screenSession->PropertyChange(property, reason);
534 TLOGI(WmsLogTag::DMS, "screenBounds : width_= %{public}f, height_= %{public}f",
535 screenSession->GetScreenProperty().GetBounds().rect_.width_,
536 screenSession->GetScreenProperty().GetBounds().rect_.height_);
537 ScreenSessionManager::GetInstance().NotifyDisplayChanged(screenSession->ConvertToDisplayInfo(),
538 DisplayChangeEvent::DISPLAY_SIZE_CHANGED);
539 }
540
ChangeScreenDisplayModeToMainOnBootAnimation(sptr<ScreenSession> screenSession)541 void SingleDisplayPocketFoldPolicy::ChangeScreenDisplayModeToMainOnBootAnimation(sptr<ScreenSession> screenSession)
542 {
543 TLOGI(WmsLogTag::DMS, "enter!");
544 screenProperty_ = ScreenSessionManager::GetInstance().GetPhyScreenProperty(SCREEN_ID_MAIN);
545 screenSession->UpdatePropertyByFoldControl(screenProperty_);
546 screenSession->PropertyChange(screenSession->GetScreenProperty(),
547 ScreenPropertyChangeReason::FOLD_SCREEN_FOLDING);
548 TLOGI(WmsLogTag::DMS, "screenBounds : width_= %{public}f, height_= %{public}f",
549 screenSession->GetScreenProperty().GetBounds().rect_.width_,
550 screenSession->GetScreenProperty().GetBounds().rect_.height_);
551 screenId_ = SCREEN_ID_MAIN;
552 }
553
ChangeScreenDisplayModeToFullOnBootAnimation(sptr<ScreenSession> screenSession)554 void SingleDisplayPocketFoldPolicy::ChangeScreenDisplayModeToFullOnBootAnimation(sptr<ScreenSession> screenSession)
555 {
556 TLOGI(WmsLogTag::DMS, "enter!");
557 screenProperty_ = ScreenSessionManager::GetInstance().GetPhyScreenProperty(SCREEN_ID_FULL);
558 screenSession->UpdatePropertyByFoldControl(screenProperty_);
559 screenSession->PropertyChange(screenSession->GetScreenProperty(),
560 ScreenPropertyChangeReason::FOLD_SCREEN_EXPAND);
561 TLOGI(WmsLogTag::DMS, "screenBounds : width_= %{public}f, height_= %{public}f",
562 screenSession->GetScreenProperty().GetBounds().rect_.width_,
563 screenSession->GetScreenProperty().GetBounds().rect_.height_);
564 screenId_ = SCREEN_ID_FULL;
565 }
566
BootAnimationFinishPowerInit()567 void SingleDisplayPocketFoldPolicy::BootAnimationFinishPowerInit()
568 {
569 int64_t timeStamp = 50;
570 if (RSInterfaces::GetInstance().GetActiveScreenId() == SCREEN_ID_FULL) {
571 // coordination to full: power off main screen
572 TLOGI(WmsLogTag::DMS, "Fold Screen Power main screen off.");
573 ScreenSessionManager::GetInstance().SetRSScreenPowerStatus(SCREEN_ID_MAIN, ScreenPowerStatus::POWER_STATUS_OFF);
574 } else if (RSInterfaces::GetInstance().GetActiveScreenId() == SCREEN_ID_MAIN) {
575 // coordination to main: power off both and power on main screen
576 TLOGI(WmsLogTag::DMS, "Fold Screen Power all screen off.");
577 ScreenSessionManager::GetInstance().SetRSScreenPowerStatus(SCREEN_ID_MAIN, ScreenPowerStatus::POWER_STATUS_OFF);
578 ScreenSessionManager::GetInstance().SetRSScreenPowerStatus(SCREEN_ID_FULL, ScreenPowerStatus::POWER_STATUS_OFF);
579
580 std::this_thread::sleep_for(std::chrono::milliseconds(timeStamp));
581 TLOGI(WmsLogTag::DMS, "Fold Screen Power main screen on.");
582 ScreenSessionManager::GetInstance().SetRSScreenPowerStatus(SCREEN_ID_MAIN, ScreenPowerStatus::POWER_STATUS_ON);
583 } else {
584 TLOGI(WmsLogTag::DMS, "Fold Screen Power Init, invalid active screen id");
585 }
586 }
587
ChangeOnTentMode(FoldStatus currentState)588 void SingleDisplayPocketFoldPolicy::ChangeOnTentMode(FoldStatus currentState)
589 {
590 TLOGI(WmsLogTag::DMS, "Enter tent mode, current state:%{public}d, change display mode to MAIN", currentState);
591 if (currentState == FoldStatus::EXPAND || currentState == FoldStatus::HALF_FOLD) {
592 ChangeScreenDisplayMode(FoldDisplayMode::MAIN);
593 } else if (currentState == FoldStatus::FOLDED) {
594 ChangeScreenDisplayMode(FoldDisplayMode::MAIN);
595 PowerMgr::PowerMgrClient::GetInstance().WakeupDeviceAsync();
596 } else {
597 TLOGE(WmsLogTag::DMS, "current state:%{public}d invalid", currentState);
598 }
599 }
600
ChangeOffTentMode()601 void SingleDisplayPocketFoldPolicy::ChangeOffTentMode()
602 {
603 PowerMgr::PowerMgrClient::GetInstance().WakeupDeviceAsync();
604 FoldDisplayMode displayMode = GetModeMatchStatus();
605 ChangeScreenDisplayMode(displayMode);
606 }
607
AddOrRemoveDisplayNodeToTree(ScreenId screenId,int32_t command)608 void SingleDisplayPocketFoldPolicy::AddOrRemoveDisplayNodeToTree(ScreenId screenId, int32_t command)
609 {
610 TLOGI(WmsLogTag::DMS, "screenId: %{public}" PRIu64 ", command: %{public}d",
611 screenId, command);
612 sptr<ScreenSession> screenSession = ScreenSessionManager::GetInstance().GetScreenSession(screenId);
613 if (screenSession == nullptr) {
614 TLOGE(WmsLogTag::DMS, "screenSession is null");
615 return;
616 }
617 std::shared_ptr<RSDisplayNode> displayNode = screenSession->GetDisplayNode();
618 if (displayNode == nullptr) {
619 TLOGE(WmsLogTag::DMS, "displayNode is null");
620 return;
621 }
622 if (command == ADD_DISPLAY_NODE) {
623 displayNode->AddDisplayNodeToTree();
624 } else if (command == REMOVE_DISPLAY_NODE) {
625 displayNode->RemoveDisplayNodeFromTree();
626 }
627 displayNode = nullptr;
628 TLOGI(WmsLogTag::DMS, "add or remove displayNode");
629 RSTransactionAdapter::FlushImplicitTransaction(screenSession->GetRSUIContext());
630 }
631
ChangeScreenDisplayModeToCoordination()632 void SingleDisplayPocketFoldPolicy::ChangeScreenDisplayModeToCoordination()
633 {
634 std::lock_guard<std::mutex> lock(coordinationMutex_);
635 if (ScreenSessionManager::GetInstance().GetCoordinationFlag()) {
636 TLOGW(WmsLogTag::DMS, "change displaymode to coordination skipped, current coordination flag is true");
637 return;
638 }
639 TLOGI(WmsLogTag::DMS, "change displaymode to coordination current mode=%{public}d", currentDisplayMode_);
640
641 ScreenSessionManager::GetInstance().SetCoordinationFlag(true);
642 ScreenSessionManager::GetInstance().OnScreenChange(SCREEN_ID_MAIN, ScreenEvent::CONNECTED);
643
644 // on main screen
645 auto taskScreenOnMainOn = [=] {
646 TLOGNI(WmsLogTag::DMS, "ChangeScreenDisplayModeToCoordination: screenIdMain ON.");
647 NotifyRefreshRateEvent(true);
648 ChangeScreenDisplayModePower(SCREEN_ID_MAIN, ScreenPowerStatus::POWER_STATUS_ON);
649 PowerMgr::PowerMgrClient::GetInstance().RefreshActivity();
650 };
651 screenPowerTaskScheduler_->PostAsyncTask(taskScreenOnMainOn, "ScreenToCoordinationTask");
652 AddOrRemoveDisplayNodeToTree(SCREEN_ID_MAIN, ADD_DISPLAY_NODE);
653 }
654
CloseCoordinationScreen()655 void SingleDisplayPocketFoldPolicy::CloseCoordinationScreen()
656 {
657 std::lock_guard<std::mutex> lock(coordinationMutex_);
658 if (!ScreenSessionManager::GetInstance().GetCoordinationFlag()) {
659 TLOGW(WmsLogTag::DMS, "change displaymode to coordination skipped, current coordination flag is false");
660 return;
661 }
662 TLOGI(WmsLogTag::DMS, "Close Coordination Screen current mode=%{public}d", currentDisplayMode_);
663
664 // on main screen
665 auto taskScreenOnMainOFF = [=] {
666 TLOGNI(WmsLogTag::DMS, "CloseCoordinationScreen: screenIdMain OFF.");
667 ChangeScreenDisplayModePower(SCREEN_ID_MAIN, ScreenPowerStatus::POWER_STATUS_OFF);
668 NotifyRefreshRateEvent(false);
669 };
670 screenPowerTaskScheduler_->PostAsyncTask(taskScreenOnMainOFF, "CloseCoordinationScreenTask");
671 AddOrRemoveDisplayNodeToTree(SCREEN_ID_MAIN, REMOVE_DISPLAY_NODE);
672
673 ScreenSessionManager::GetInstance().OnScreenChange(SCREEN_ID_MAIN, ScreenEvent::DISCONNECTED);
674 ScreenSessionManager::GetInstance().SetCoordinationFlag(false);
675 }
676
GetAllCreaseRegion(std::vector<FoldCreaseRegionItem> & foldCreaseRegionItems) const677 void SingleDisplayPocketFoldPolicy::GetAllCreaseRegion(std::vector<FoldCreaseRegionItem>& foldCreaseRegionItems) const
678 {
679 FoldCreaseRegionItem MCreaseItem{DisplayOrientation::LANDSCAPE, FoldDisplayMode::MAIN,
680 FoldCreaseRegion(0, {})};
681 FoldCreaseRegionItem FPorCreaseItem{DisplayOrientation::PORTRAIT, FoldDisplayMode::FULL,
682 GetFoldCreaseRegion(false)};
683 FoldCreaseRegionItem FLandCreaseItem{DisplayOrientation::LANDSCAPE, FoldDisplayMode::FULL,
684 GetFoldCreaseRegion(true)};
685 FoldCreaseRegionItem CPorCreaseItem{DisplayOrientation::PORTRAIT, FoldDisplayMode::COORDINATION,
686 GetFoldCreaseRegion(false)};
687 FoldCreaseRegionItem CLandCreaseItem{DisplayOrientation::LANDSCAPE, FoldDisplayMode::COORDINATION,
688 GetFoldCreaseRegion(true)};
689 foldCreaseRegionItems.push_back(MCreaseItem);
690 foldCreaseRegionItems.push_back(FPorCreaseItem);
691 foldCreaseRegionItems.push_back(FLandCreaseItem);
692 foldCreaseRegionItems.push_back(CPorCreaseItem);
693 foldCreaseRegionItems.push_back(CLandCreaseItem);
694 }
695
ExitCoordination()696 void SingleDisplayPocketFoldPolicy::ExitCoordination()
697 {
698 std::lock_guard<std::mutex> lock(coordinationMutex_);
699 if (!ScreenSessionManager::GetInstance().GetCoordinationFlag()) {
700 TLOGW(WmsLogTag::DMS, "change displaymode to coordination skipped, current coordination flag is false");
701 return;
702 }
703 ChangeScreenDisplayModePower(SCREEN_ID_MAIN, ScreenPowerStatus::POWER_STATUS_OFF);
704 AddOrRemoveDisplayNodeToTree(SCREEN_ID_MAIN, REMOVE_DISPLAY_NODE);
705 ScreenSessionManager::GetInstance().OnScreenChange(SCREEN_ID_MAIN, ScreenEvent::DISCONNECTED);
706 ScreenSessionManager::GetInstance().SetCoordinationFlag(false);
707 NotifyRefreshRateEvent(false);
708 FoldDisplayMode displayMode = GetModeMatchStatus();
709 currentDisplayMode_ = displayMode;
710 lastDisplayMode_ = displayMode;
711 TLOGI(WmsLogTag::DMS, "Exit coordination, current display mode:%{public}d", displayMode);
712 ScreenSessionManager::GetInstance().NotifyDisplayModeChanged(displayMode);
713 }
714
NotifyRefreshRateEvent(bool isEventStatus)715 void SingleDisplayPocketFoldPolicy::NotifyRefreshRateEvent(bool isEventStatus)
716 {
717 EventInfo eventInfo = {
718 .eventName = "VOTER_MULTISELFOWNEDSCREEN",
719 .eventStatus = isEventStatus,
720 .minRefreshRate = 60,
721 .maxRefreshRate = 60,
722 };
723 RSInterfaces::GetInstance().NotifyRefreshRateEvent(eventInfo);
724 }
725 } // namespace OHOS::Rosen