• 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 <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