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 <transaction/rs_interfaces.h>
19 #include "fold_screen_controller/single_display_pocket_fold_policy.h"
20 #include "session/screen/include/screen_session.h"
21 #include "screen_session_manager.h"
22 
23 #include "window_manager_hilog.h"
24 
25 #ifdef POWER_MANAGER_ENABLE
26 #include <power_mgr_client.h>
27 #endif
28 
29 namespace OHOS::Rosen {
30 namespace {
31 const ScreenId SCREEN_ID_FULL = 0;
32 const ScreenId SCREEN_ID_MAIN = 5;
33 
34 const int32_t REMOVE_DISPLAY_NODE = 0;
35 const int32_t ADD_DISPLAY_NODE = 1;
36 
37 #ifdef TP_FEATURE_ENABLE
38 const int32_t TP_TYPE = 12;
39 const int32_t TP_TYPE_POWER_CTRL = 18;
40 const std::string FULL_TP = "0";
41 const std::string MAIN_TP = "1";
42 const std::string MAIN_TP_OFF = "1,1";
43 const std::string FULL_TP_OFF = "0,1";
44 #endif
45 } // namespace
46 
SingleDisplayPocketFoldPolicy(std::recursive_mutex & displayInfoMutex,std::shared_ptr<TaskScheduler> screenPowerTaskScheduler)47 SingleDisplayPocketFoldPolicy::SingleDisplayPocketFoldPolicy(std::recursive_mutex& displayInfoMutex,
48     std::shared_ptr<TaskScheduler> screenPowerTaskScheduler)
49     : displayInfoMutex_(displayInfoMutex), screenPowerTaskScheduler_(screenPowerTaskScheduler)
50 {
51     TLOGI(WmsLogTag::DMS, "SingleDisplayPocketFoldPolicy created");
52 
53     ScreenId screenIdFull = 0;
54     int32_t foldCreaseRegionPosX = 0;
55     int32_t foldCreaseRegionPosY = 1064;
56     int32_t foldCreaseRegionPosWidth = 2496;
57     int32_t foldCreaseRegionPosHeight = 171;
58 
59     std::vector<DMRect> rect = {
60         {
61             foldCreaseRegionPosX, foldCreaseRegionPosY,
62             foldCreaseRegionPosWidth, foldCreaseRegionPosHeight
63         }
64     };
65     currentFoldCreaseRegion_ = new FoldCreaseRegion(screenIdFull, rect);
66 }
67 
SetdisplayModeChangeStatus(bool status,bool isOnBootAnimation)68 void SingleDisplayPocketFoldPolicy::SetdisplayModeChangeStatus(bool status, bool isOnBootAnimation)
69 {
70     if (status) {
71         pengdingTask_ = isOnBootAnimation ? FOLD_TO_EXPAND_ONBOOTANIMATION_TASK_NUM : FOLD_TO_EXPAND_TASK_NUM;
72         startTimePoint_ = std::chrono::steady_clock::now();
73         displayModeChangeRunning_ = status;
74     } else {
75         pengdingTask_ --;
76         if (pengdingTask_ != 0) {
77             return;
78         }
79         displayModeChangeRunning_ = false;
80         endTimePoint_ = std::chrono::steady_clock::now();
81         if (lastCachedisplayMode_.load() != GetScreenDisplayMode()) {
82             ScreenSessionManager::GetInstance().TriggerDisplayModeUpdate(lastCachedisplayMode_.load());
83         }
84     }
85 }
86 
ChangeScreenDisplayMode(FoldDisplayMode displayMode,DisplayModeChangeReason reason)87 void SingleDisplayPocketFoldPolicy::ChangeScreenDisplayMode(FoldDisplayMode displayMode,
88     DisplayModeChangeReason reason)
89 {
90     SetLastCacheDisplayMode(displayMode);
91     if (GetModeChangeRunningStatus()) {
92         TLOGW(WmsLogTag::DMS, "last process not complete, skip mode: %{public}d", displayMode);
93         return;
94     }
95     TLOGI(WmsLogTag::DMS, "start change displaymode: %{public}d, lastElapsedMs: %{public}" PRId64 "ms",
96         displayMode, getFoldingElapsedMs());
97 
98     sptr<ScreenSession> screenSession = ScreenSessionManager::GetInstance().GetScreenSession(SCREEN_ID_FULL);
99     if (screenSession == nullptr) {
100         TLOGE(WmsLogTag::DMS, "default screenSession is null");
101         return;
102     }
103     HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "ssm:ChangeScreenDisplayMode(displayMode = %" PRIu64")", displayMode);
104     {
105         std::lock_guard<std::recursive_mutex> lock_mode(displayModeMutex_);
106         if (currentDisplayMode_ == displayMode) {
107             TLOGW(WmsLogTag::DMS, "ChangeScreenDisplayMode already in displayMode %{public}d", displayMode);
108             return;
109         }
110     }
111     ReportFoldDisplayModeChange(displayMode);
112     ChangeScreenDisplayModeProc(screenSession, displayMode, reason);
113     {
114         std::lock_guard<std::recursive_mutex> lock_mode(displayModeMutex_);
115         currentDisplayMode_ = displayMode;
116         lastDisplayMode_ = displayMode;
117     }
118     ScreenSessionManager::GetInstance().NotifyDisplayModeChanged(displayMode);
119 }
120 
ChangeScreenDisplayModeProc(sptr<ScreenSession> screenSession,FoldDisplayMode displayMode,DisplayModeChangeReason reason)121 void SingleDisplayPocketFoldPolicy::ChangeScreenDisplayModeProc(sptr<ScreenSession> screenSession,
122     FoldDisplayMode displayMode, DisplayModeChangeReason reason)
123 {
124     switch (displayMode) {
125         case FoldDisplayMode::MAIN: {
126             if (currentDisplayMode_ == FoldDisplayMode::COORDINATION) {
127                 CloseCoordinationScreen();
128             }
129             ChangeScreenDisplayModeToMain(screenSession);
130             break;
131         }
132         case FoldDisplayMode::FULL: {
133             if (currentDisplayMode_ == FoldDisplayMode::COORDINATION) {
134                 CloseCoordinationScreen();
135             } else {
136                 ChangeScreenDisplayModeToFull(screenSession, reason);
137             }
138             break;
139         }
140         case FoldDisplayMode::COORDINATION: {
141             ChangeScreenDisplayModeToCoordination();
142             break;
143         }
144         case FoldDisplayMode::UNKNOWN: {
145             TLOGI(WmsLogTag::DMS, "ChangeScreenDisplayMode displayMode is unknown");
146             break;
147         }
148         default: {
149             TLOGI(WmsLogTag::DMS, "ChangeScreenDisplayMode displayMode is invalid");
150             break;
151         }
152     }
153 }
154 
SendSensorResult(FoldStatus foldStatus)155 void SingleDisplayPocketFoldPolicy::SendSensorResult(FoldStatus foldStatus)
156 {
157     TLOGI(WmsLogTag::DMS, "SendSensorResult FoldStatus: %{public}d", foldStatus);
158     FoldDisplayMode displayMode = GetModeMatchStatus();
159     if (!(currentDisplayMode_ == FoldDisplayMode::COORDINATION &&
160         displayMode == FoldDisplayMode::FULL)) {
161         ChangeScreenDisplayMode(displayMode);
162     }
163 }
164 
GetCurrentFoldCreaseRegion()165 sptr<FoldCreaseRegion> SingleDisplayPocketFoldPolicy::GetCurrentFoldCreaseRegion()
166 {
167     TLOGI(WmsLogTag::DMS, "GetCurrentFoldCreaseRegion");
168     return currentFoldCreaseRegion_;
169 }
170 
LockDisplayStatus(bool locked)171 void SingleDisplayPocketFoldPolicy::LockDisplayStatus(bool locked)
172 {
173     TLOGI(WmsLogTag::DMS, "LockDisplayStatus locked: %{public}d", locked);
174     lockDisplayStatus_ = locked;
175 }
176 
SetOnBootAnimation(bool onBootAnimation)177 void SingleDisplayPocketFoldPolicy::SetOnBootAnimation(bool onBootAnimation)
178 {
179     TLOGI(WmsLogTag::DMS, "SetOnBootAnimation onBootAnimation: %{public}d", onBootAnimation);
180     onBootAnimation_ = onBootAnimation;
181     if (!onBootAnimation_) {
182         TLOGI(WmsLogTag::DMS, "SetOnBootAnimation when boot animation finished, change display mode");
183         RecoverWhenBootAnimationExit();
184         NotifyRefreshRateEvent(false);
185     } else {
186         NotifyRefreshRateEvent(true);
187     }
188 }
189 
RecoverWhenBootAnimationExit()190 void SingleDisplayPocketFoldPolicy::RecoverWhenBootAnimationExit()
191 {
192     TLOGI(WmsLogTag::DMS, "RecoverWhenBootAnimationExit currentScreen(%{public}" PRIu64 ")", screenId_);
193     FoldDisplayMode displayMode = GetModeMatchStatus();
194     if (currentDisplayMode_ != displayMode) {
195         ChangeScreenDisplayMode(displayMode);
196     }
197 }
198 
UpdateForPhyScreenPropertyChange()199 void SingleDisplayPocketFoldPolicy::UpdateForPhyScreenPropertyChange()
200 {
201     TLOGI(WmsLogTag::DMS, "UpdateForPhyScreenPropertyChange CurrentScreen(%{public}" PRIu64 ")", screenId_);
202     FoldDisplayMode displayMode = GetModeMatchStatus();
203     if (currentDisplayMode_ != displayMode) {
204         ChangeScreenDisplayMode(displayMode);
205     }
206 }
207 
GetModeMatchStatus()208 FoldDisplayMode SingleDisplayPocketFoldPolicy::GetModeMatchStatus()
209 {
210     FoldDisplayMode displayMode = FoldDisplayMode::UNKNOWN;
211     switch (currentFoldStatus_) {
212         case FoldStatus::EXPAND: {
213             displayMode = FoldDisplayMode::FULL;
214             break;
215         }
216         case FoldStatus::FOLDED: {
217             displayMode = FoldDisplayMode::MAIN;
218             break;
219         }
220         case FoldStatus::HALF_FOLD: {
221             displayMode = FoldDisplayMode::FULL;
222             break;
223         }
224         default: {
225             TLOGI(WmsLogTag::DMS, "GetModeMatchStatus FoldStatus is invalid");
226         }
227     }
228     return displayMode;
229 }
230 
ReportFoldDisplayModeChange(FoldDisplayMode displayMode)231 void SingleDisplayPocketFoldPolicy::ReportFoldDisplayModeChange(FoldDisplayMode displayMode)
232 {
233     int32_t mode = static_cast<int32_t>(displayMode);
234     TLOGI(WmsLogTag::DMS, "ReportFoldDisplayModeChange displayMode: %{public}d", mode);
235     int32_t ret = HiSysEventWrite(
236         OHOS::HiviewDFX::HiSysEvent::Domain::WINDOW_MANAGER,
237         "DISPLAY_MODE",
238         OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR,
239         "FOLD_DISPLAY_MODE", mode);
240     if (ret != 0) {
241         TLOGE(WmsLogTag::DMS, "ReportFoldDisplayModeChange Write HiSysEvent error, ret: %{public}d", ret);
242     }
243 }
244 
ReportFoldStatusChangeBegin(int32_t offScreen,int32_t onScreen)245 void SingleDisplayPocketFoldPolicy::ReportFoldStatusChangeBegin(int32_t offScreen, int32_t onScreen)
246 {
247     TLOGI(WmsLogTag::DMS, "ReportFoldStatusChangeBegin offScreen: %{public}d, onScreen: %{public}d",
248         offScreen, onScreen);
249     int32_t ret = HiSysEventWrite(
250         OHOS::HiviewDFX::HiSysEvent::Domain::WINDOW_MANAGER,
251         "FOLD_STATE_CHANGE_BEGIN",
252         OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR,
253         "POWER_OFF_SCREEN", offScreen,
254         "POWER_ON_SCREEN", onScreen);
255     if (ret != 0) {
256         TLOGE(WmsLogTag::DMS, "ReportFoldStatusChangeBegin Write HiSysEvent error, ret: %{public}d", ret);
257     }
258 }
259 
ChangeScreenDisplayModeToMainWhenFoldScreenOn(sptr<ScreenSession> screenSession)260 void SingleDisplayPocketFoldPolicy::ChangeScreenDisplayModeToMainWhenFoldScreenOn(sptr<ScreenSession> screenSession)
261 {
262     TLOGI(WmsLogTag::DMS, "IsFoldScreenOn is true, begin.");
263     ReportFoldStatusChangeBegin(static_cast<int32_t>(SCREEN_ID_FULL),
264         static_cast<int32_t>(SCREEN_ID_MAIN));
265     auto taskScreenOnMain = [=] {
266         // off full screen
267         TLOGI(WmsLogTag::DMS, "ChangeScreenDisplayModeToMain: IsFoldScreenOn is true, screenIdFull OFF.");
268         screenId_ = SCREEN_ID_FULL;
269         ChangeScreenDisplayModePower(ScreenPowerStatus::POWER_STATUS_OFF);
270         SetdisplayModeChangeStatus(false);
271 
272         // on main screen
273         TLOGI(WmsLogTag::DMS, "ChangeScreenDisplayModeToMain: IsFoldScreenOn is true, screenIdMain ON.");
274         screenId_ = SCREEN_ID_MAIN;
275         ChangeScreenDisplayModePower(ScreenPowerStatus::POWER_STATUS_ON);
276         SetdisplayModeChangeStatus(false);
277     };
278     screenPowerTaskScheduler_->PostAsyncTask(taskScreenOnMain, "screenOnMainTask");
279     SendPropertyChangeResult(screenSession, SCREEN_ID_MAIN, ScreenPropertyChangeReason::FOLD_SCREEN_FOLDING);
280 }
281 
ChangeScreenDisplayModeToMainWhenFoldScreenOff(sptr<ScreenSession> screenSession)282 void SingleDisplayPocketFoldPolicy::ChangeScreenDisplayModeToMainWhenFoldScreenOff(sptr<ScreenSession> screenSession)
283 {
284     TLOGI(WmsLogTag::DMS, "IsFoldScreenOn is false, begin.");
285     // off full screen
286     auto taskScreenOffMainOff = [=] {
287         TLOGI(WmsLogTag::DMS, "ChangeScreenDisplayModeToMain: IsFoldScreenOn is false, screenIdFull OFF.");
288         screenId_ = SCREEN_ID_FULL;
289         ChangeScreenDisplayModePower(ScreenPowerStatus::POWER_STATUS_OFF);
290         SetdisplayModeChangeStatus(false);
291     };
292     screenPowerTaskScheduler_->PostAsyncTask(taskScreenOffMainOff, "screenOffMainOffTask");
293     SendPropertyChangeResult(screenSession, SCREEN_ID_MAIN, ScreenPropertyChangeReason::FOLD_SCREEN_FOLDING);
294     bool ifTentMode = ScreenSessionManager::GetInstance().GetTentMode();
295     auto taskScreenOnMainChangeScreenId = [=] {
296         TLOGI(WmsLogTag::DMS, "ChangeScreenDisplayModeToMain: IsFoldScreenOn is false, Change ScreenId to Main.");
297         screenId_ = SCREEN_ID_MAIN;
298 #ifdef TP_FEATURE_ENABLE
299         RSInterfaces::GetInstance().SetTpFeatureConfig(TP_TYPE_POWER_CTRL, MAIN_TP_OFF.c_str());
300 #endif
301         if (ifTentMode) {
302             PowerMgr::PowerMgrClient::GetInstance().WakeupDeviceAsync();
303         }
304         SetdisplayModeChangeStatus(false);
305     };
306     screenPowerTaskScheduler_->PostAsyncTask(taskScreenOnMainChangeScreenId, "taskScreenOnMainChangeScreenId");
307 }
308 
309 
ChangeScreenDisplayModeToMain(sptr<ScreenSession> screenSession,DisplayModeChangeReason reason)310 void SingleDisplayPocketFoldPolicy::ChangeScreenDisplayModeToMain(sptr<ScreenSession> screenSession,
311     DisplayModeChangeReason reason)
312 {
313     SetdisplayModeChangeStatus(true);
314     if (onBootAnimation_) {
315         SetdisplayModeChangeStatus(true, true);
316         ChangeScreenDisplayModeToMainOnBootAnimation(screenSession);
317         return;
318     }
319     #ifdef TP_FEATURE_ENABLE
320     RSInterfaces::GetInstance().SetTpFeatureConfig(TP_TYPE, MAIN_TP.c_str());
321     #endif
322     if (PowerMgr::PowerMgrClient::GetInstance().IsFoldScreenOn()) {
323         ChangeScreenDisplayModeToMainWhenFoldScreenOn(screenSession);
324     } else { // When the screen is off and folded, it is not powered on
325         ScreenSessionManager::GetInstance().ForceSkipScreenOffAnimation();
326         ChangeScreenDisplayModeToMainWhenFoldScreenOff(screenSession);
327     }
328 }
329 
ChangeScreenDisplayModeToFullWhenFoldScreenOn(sptr<ScreenSession> screenSession)330 void SingleDisplayPocketFoldPolicy::ChangeScreenDisplayModeToFullWhenFoldScreenOn(sptr<ScreenSession> screenSession)
331 {
332     TLOGI(WmsLogTag::DMS, "IsFoldScreenOn is true, begin.");
333     auto taskScreenOnFull = [=] {
334         // off main screen
335         TLOGI(WmsLogTag::DMS, "ChangeScreenDisplayModeToFull: IsFoldScreenOn is true, screenIdMain OFF.");
336         screenId_ = SCREEN_ID_MAIN;
337         ChangeScreenDisplayModePower(ScreenPowerStatus::POWER_STATUS_OFF);
338         SetdisplayModeChangeStatus(false);
339 
340         // on full screen
341         TLOGI(WmsLogTag::DMS, "ChangeScreenDisplayModeToFull: IsFoldScreenOn is true, screenIdFull ON.");
342         screenId_ = SCREEN_ID_FULL;
343         ChangeScreenDisplayModePower(ScreenPowerStatus::POWER_STATUS_ON);
344         SetdisplayModeChangeStatus(false);
345     };
346     screenPowerTaskScheduler_->PostAsyncTask(taskScreenOnFull, "screenOnFullTask");
347     SendPropertyChangeResult(screenSession, SCREEN_ID_FULL, ScreenPropertyChangeReason::FOLD_SCREEN_EXPAND);
348 }
349 
ChangeScreenDisplayModeToFullWhenFoldScreenOff(sptr<ScreenSession> screenSession,DisplayModeChangeReason reason)350 void SingleDisplayPocketFoldPolicy::ChangeScreenDisplayModeToFullWhenFoldScreenOff(sptr<ScreenSession> screenSession,
351     DisplayModeChangeReason reason)
352 {
353     TLOGI(WmsLogTag::DMS, "IsFoldScreenOn is false, begin.");
354     // off main screen
355     auto taskScreenOffFullOff = [=] {
356         TLOGI(WmsLogTag::DMS, "ChangeScreenDisplayModeToFull: IsFoldScreenOn is false, screenIdMain OFF.");
357         screenId_ = SCREEN_ID_MAIN;
358         ChangeScreenDisplayModePower(ScreenPowerStatus::POWER_STATUS_OFF);
359         SetdisplayModeChangeStatus(false);
360     };
361     screenPowerTaskScheduler_->PostAsyncTask(taskScreenOffFullOff, "screenOffFullOffTask");
362     SendPropertyChangeResult(screenSession, SCREEN_ID_FULL, ScreenPropertyChangeReason::FOLD_SCREEN_EXPAND);
363     // on full screen
364     auto taskScreenOnFullOn = [=] {
365         TLOGI(WmsLogTag::DMS, "ChangeScreenDisplayModeToFull: IsFoldScreenOn is false, screenIdFull ON.");
366         screenId_ = SCREEN_ID_FULL;
367         if (reason == DisplayModeChangeReason::RECOVER) {
368 #ifdef TP_FEATURE_ENABLE
369             RSInterfaces::GetInstance().SetTpFeatureConfig(TP_TYPE_POWER_CTRL, FULL_TP_OFF.c_str());
370 #endif
371         } else {
372             PowerMgr::PowerMgrClient::GetInstance().WakeupDeviceAsync();
373         }
374         SetdisplayModeChangeStatus(false);
375     };
376     screenPowerTaskScheduler_->PostAsyncTask(taskScreenOnFullOn, "screenOnFullOnTask");
377 }
378 
ChangeScreenDisplayModeToFull(sptr<ScreenSession> screenSession,DisplayModeChangeReason reason)379 void SingleDisplayPocketFoldPolicy::ChangeScreenDisplayModeToFull(sptr<ScreenSession> screenSession,
380     DisplayModeChangeReason reason)
381 {
382     SetdisplayModeChangeStatus(true);
383     if (onBootAnimation_) {
384         SetdisplayModeChangeStatus(true, true);
385         ChangeScreenDisplayModeToFullOnBootAnimation(screenSession);
386         return;
387     }
388     ReportFoldStatusChangeBegin((int32_t)SCREEN_ID_MAIN, (int32_t)SCREEN_ID_FULL);
389 #ifdef TP_FEATURE_ENABLE
390     RSInterfaces::GetInstance().SetTpFeatureConfig(TP_TYPE, FULL_TP.c_str());
391 #endif
392     if (PowerMgr::PowerMgrClient::GetInstance().IsFoldScreenOn()) {
393         ChangeScreenDisplayModeToFullWhenFoldScreenOn(screenSession);
394     } else { //AOD scene
395         if (ScreenSessionManager::GetInstance().TryToCancelScreenOff()) {
396             ChangeScreenDisplayModeToFullWhenFoldScreenOn(screenSession);
397         } else {
398             ChangeScreenDisplayModeToFullWhenFoldScreenOff(screenSession, reason);
399         }
400     }
401 }
402 
ChangeScreenDisplayModePower(ScreenPowerStatus screenPowerStatus)403 void SingleDisplayPocketFoldPolicy::ChangeScreenDisplayModePower(ScreenPowerStatus screenPowerStatus)
404 {
405     ScreenSessionManager::GetInstance().SetKeyguardDrawnDoneFlag(false);
406     ScreenSessionManager::GetInstance().SetScreenPowerForFold(screenPowerStatus);
407 }
408 
SendPropertyChangeResult(sptr<ScreenSession> screenSession,ScreenId screenId,ScreenPropertyChangeReason reason)409 void SingleDisplayPocketFoldPolicy::SendPropertyChangeResult(sptr<ScreenSession> screenSession, ScreenId screenId,
410     ScreenPropertyChangeReason reason)
411 {
412     std::lock_guard<std::recursive_mutex> lock_info(displayInfoMutex_);
413     screenProperty_ = ScreenSessionManager::GetInstance().GetPhyScreenProperty(screenId);
414     screenSession->UpdatePropertyByFoldControl(screenProperty_);
415     screenSession->PropertyChange(screenSession->GetScreenProperty(), reason);
416     screenSession->SetRotationAndScreenRotationOnly(Rotation::ROTATION_0);
417     TLOGI(WmsLogTag::DMS, "screenBounds : width_= %{public}f, height_= %{public}f",
418         screenSession->GetScreenProperty().GetBounds().rect_.width_,
419         screenSession->GetScreenProperty().GetBounds().rect_.height_);
420     ScreenSessionManager::GetInstance().NotifyDisplayChanged(screenSession->ConvertToDisplayInfo(),
421         DisplayChangeEvent::DISPLAY_SIZE_CHANGED);
422 }
423 
ChangeScreenDisplayModeToMainOnBootAnimation(sptr<ScreenSession> screenSession)424 void SingleDisplayPocketFoldPolicy::ChangeScreenDisplayModeToMainOnBootAnimation(sptr<ScreenSession> screenSession)
425 {
426     TLOGI(WmsLogTag::DMS, "ChangeScreenDisplayModeToMainOnBootAnimation");
427     screenProperty_ = ScreenSessionManager::GetInstance().GetPhyScreenProperty(SCREEN_ID_MAIN);
428     screenSession->UpdatePropertyByFoldControl(screenProperty_);
429     screenSession->PropertyChange(screenSession->GetScreenProperty(),
430         ScreenPropertyChangeReason::FOLD_SCREEN_FOLDING);
431     TLOGI(WmsLogTag::DMS, "screenBounds : width_= %{public}f, height_= %{public}f",
432         screenSession->GetScreenProperty().GetBounds().rect_.width_,
433         screenSession->GetScreenProperty().GetBounds().rect_.height_);
434     screenId_ = SCREEN_ID_MAIN;
435 }
436 
ChangeScreenDisplayModeToFullOnBootAnimation(sptr<ScreenSession> screenSession)437 void SingleDisplayPocketFoldPolicy::ChangeScreenDisplayModeToFullOnBootAnimation(sptr<ScreenSession> screenSession)
438 {
439     TLOGI(WmsLogTag::DMS, "ChangeScreenDisplayModeToFullOnBootAnimation");
440     screenProperty_ = ScreenSessionManager::GetInstance().GetPhyScreenProperty(SCREEN_ID_FULL);
441     screenSession->UpdatePropertyByFoldControl(screenProperty_);
442     screenSession->PropertyChange(screenSession->GetScreenProperty(),
443         ScreenPropertyChangeReason::FOLD_SCREEN_EXPAND);
444     TLOGI(WmsLogTag::DMS, "screenBounds : width_= %{public}f, height_= %{public}f",
445         screenSession->GetScreenProperty().GetBounds().rect_.width_,
446         screenSession->GetScreenProperty().GetBounds().rect_.height_);
447     screenId_ = SCREEN_ID_FULL;
448 }
449 
BootAnimationFinishPowerInit()450 void SingleDisplayPocketFoldPolicy::BootAnimationFinishPowerInit()
451 {
452     int64_t timeStamp = 50;
453     if (RSInterfaces::GetInstance().GetActiveScreenId() == SCREEN_ID_FULL) {
454         // 同显切内屏:外屏下电
455         TLOGI(WmsLogTag::DMS, "Fold Screen Power main screen off.");
456         RSInterfaces::GetInstance().SetScreenPowerStatus(SCREEN_ID_MAIN, ScreenPowerStatus::POWER_STATUS_OFF);
457     } else if (RSInterfaces::GetInstance().GetActiveScreenId() == SCREEN_ID_MAIN) {
458         // 同显切外屏:双屏都灭再外屏上电
459         TLOGI(WmsLogTag::DMS, "Fold Screen Power all screen off.");
460         RSInterfaces::GetInstance().SetScreenPowerStatus(SCREEN_ID_MAIN, ScreenPowerStatus::POWER_STATUS_OFF);
461         RSInterfaces::GetInstance().SetScreenPowerStatus(SCREEN_ID_FULL, ScreenPowerStatus::POWER_STATUS_OFF);
462         std::this_thread::sleep_for(std::chrono::milliseconds(timeStamp));
463         TLOGI(WmsLogTag::DMS, "Fold Screen Power main screen on.");
464         RSInterfaces::GetInstance().SetScreenPowerStatus(SCREEN_ID_MAIN, ScreenPowerStatus::POWER_STATUS_ON);
465     } else {
466         TLOGI(WmsLogTag::DMS, "Fold Screen Power Init, invalid active screen id");
467     }
468 }
469 
ChangeOnTentMode(FoldStatus currentState)470 void SingleDisplayPocketFoldPolicy::ChangeOnTentMode(FoldStatus currentState)
471 {
472     TLOGI(WmsLogTag::DMS, "Enter tent mode, current state:%{public}d, change display mode to MAIN", currentState);
473     if (currentState == FoldStatus::EXPAND || currentState == FoldStatus::HALF_FOLD) {
474         ChangeScreenDisplayMode(FoldDisplayMode::MAIN);
475     } else if (currentState == FoldStatus::FOLDED) {
476         RSInterfaces::GetInstance().SetScreenPowerStatus(SCREEN_ID_FULL, ScreenPowerStatus::POWER_STATUS_OFF);
477         ChangeScreenDisplayMode(FoldDisplayMode::MAIN);
478         PowerMgr::PowerMgrClient::GetInstance().WakeupDeviceAsync();
479     } else {
480         TLOGE(WmsLogTag::DMS, "current state:%{public}d invalid", currentState);
481     }
482 }
483 
ChangeOffTentMode()484 void SingleDisplayPocketFoldPolicy::ChangeOffTentMode()
485 {
486     PowerMgr::PowerMgrClient::GetInstance().WakeupDeviceAsync();
487     FoldDisplayMode displayMode = GetModeMatchStatus();
488     ChangeScreenDisplayMode(displayMode);
489 }
490 
AddOrRemoveDisplayNodeToTree(ScreenId screenId,int32_t command)491 void SingleDisplayPocketFoldPolicy::AddOrRemoveDisplayNodeToTree(ScreenId screenId, int32_t command)
492 {
493     TLOGI(WmsLogTag::DMS, "AddOrRemoveDisplayNodeToTree, screenId: %{public}" PRIu64 ", command: %{public}d",
494         screenId, command);
495     sptr<ScreenSession> screenSession = ScreenSessionManager::GetInstance().GetScreenSession(screenId);
496     if (screenSession == nullptr) {
497         TLOGE(WmsLogTag::DMS, "AddOrRemoveDisplayNodeToTree, screenSession is null");
498         return;
499     }
500     std::shared_ptr<RSDisplayNode> displayNode = screenSession->GetDisplayNode();
501     if (displayNode == nullptr) {
502         TLOGE(WmsLogTag::DMS, "AddOrRemoveDisplayNodeToTree, displayNode is null");
503         return;
504     }
505     if (command == ADD_DISPLAY_NODE) {
506         displayNode->AddDisplayNodeToTree();
507     } else if (command == REMOVE_DISPLAY_NODE) {
508         displayNode->RemoveDisplayNodeFromTree();
509     }
510     displayNode = nullptr;
511     auto transactionProxy = RSTransactionProxy::GetInstance();
512     if (transactionProxy != nullptr) {
513         TLOGI(WmsLogTag::DMS, "add or remove displayNode");
514         transactionProxy->FlushImplicitTransaction();
515     }
516 }
517 
ChangeScreenDisplayModeToCoordination()518 void SingleDisplayPocketFoldPolicy::ChangeScreenDisplayModeToCoordination()
519 {
520     TLOGI(WmsLogTag::DMS, "change displaymode to coordination current mode=%{public}d", currentDisplayMode_);
521 
522     ScreenSessionManager::GetInstance().SetCoordinationFlag(true);
523     ScreenSessionManager::GetInstance().OnScreenChange(SCREEN_ID_MAIN, ScreenEvent::CONNECTED);
524 
525     // on main screen
526     auto taskScreenOnMainOn = [=] {
527         TLOGI(WmsLogTag::DMS, "ChangeScreenDisplayModeToCoordination: screenIdMain ON.");
528         NotifyRefreshRateEvent(true);
529         ScreenSessionManager::GetInstance().SetKeyguardDrawnDoneFlag(false);
530         ScreenSessionManager::GetInstance().SetScreenPowerForFold(SCREEN_ID_MAIN,
531             ScreenPowerStatus::POWER_STATUS_ON);
532         PowerMgr::PowerMgrClient::GetInstance().RefreshActivity();
533     };
534     screenPowerTaskScheduler_->PostAsyncTask(taskScreenOnMainOn, "ScreenToCoordinationTask");
535     AddOrRemoveDisplayNodeToTree(SCREEN_ID_MAIN, ADD_DISPLAY_NODE);
536 }
537 
CloseCoordinationScreen()538 void SingleDisplayPocketFoldPolicy::CloseCoordinationScreen()
539 {
540     TLOGI(WmsLogTag::DMS, "Close Coordination Screen current mode=%{public}d", currentDisplayMode_);
541 
542     // on main screen
543     auto taskScreenOnMainOFF = [=] {
544         TLOGI(WmsLogTag::DMS, "CloseCoordinationScreen: screenIdMain OFF.");
545         ScreenSessionManager::GetInstance().SetKeyguardDrawnDoneFlag(false);
546         ScreenSessionManager::GetInstance().SetScreenPowerForFold(SCREEN_ID_MAIN,
547             ScreenPowerStatus::POWER_STATUS_OFF);
548         NotifyRefreshRateEvent(false);
549     };
550     screenPowerTaskScheduler_->PostAsyncTask(taskScreenOnMainOFF, "CloseCoordinationScreenTask");
551     AddOrRemoveDisplayNodeToTree(SCREEN_ID_MAIN, REMOVE_DISPLAY_NODE);
552 
553     ScreenSessionManager::GetInstance().OnScreenChange(SCREEN_ID_MAIN, ScreenEvent::DISCONNECTED);
554     ScreenSessionManager::GetInstance().SetCoordinationFlag(false);
555 }
556 
ExitCoordination()557 void SingleDisplayPocketFoldPolicy::ExitCoordination()
558 {
559     ScreenSessionManager::GetInstance().SetKeyguardDrawnDoneFlag(false);
560     ScreenSessionManager::GetInstance().SetScreenPowerForFold(SCREEN_ID_MAIN,
561         ScreenPowerStatus::POWER_STATUS_OFF);
562     AddOrRemoveDisplayNodeToTree(SCREEN_ID_MAIN, REMOVE_DISPLAY_NODE);
563     ScreenSessionManager::GetInstance().OnScreenChange(SCREEN_ID_MAIN, ScreenEvent::DISCONNECTED);
564     ScreenSessionManager::GetInstance().SetCoordinationFlag(false);
565     NotifyRefreshRateEvent(false);
566     FoldDisplayMode displayMode = GetModeMatchStatus();
567     currentDisplayMode_ = displayMode;
568     lastDisplayMode_ = displayMode;
569     TLOGI(WmsLogTag::DMS, "Exit coordination, current display mode:%{public}d", displayMode);
570     ScreenSessionManager::GetInstance().NotifyDisplayModeChanged(displayMode);
571 }
572 
NotifyRefreshRateEvent(bool isEventStatus)573 void SingleDisplayPocketFoldPolicy::NotifyRefreshRateEvent(bool isEventStatus)
574 {
575     EventInfo eventInfo = {
576         .eventName = "VOTER_MULTISELFOWNEDSCREEN",
577         .eventStatus = isEventStatus,
578         .minRefreshRate = 60,
579         .maxRefreshRate = 60,
580     };
581     RSInterfaces::GetInstance().NotifyRefreshRateEvent(eventInfo);
582 }
583 } // namespace OHOS::Rosen