• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 <hitrace_meter.h>
17 #include <hisysevent.h>
18 #include "screen_session_manager/include/screen_session_manager.h"
19 #include "fold_screen_controller/super_fold_sensor_manager.h"
20 #include "window_manager_hilog.h"
21 #include "fold_screen_state_internel.h"
22 #include "fold_screen_controller/super_fold_state_manager.h"
23 #include "screen_setting_helper.h"
24 #include "parameter.h"
25 
26 namespace OHOS {
27 
28 namespace Rosen {
29 
30 WM_IMPLEMENT_SINGLE_INSTANCE(SuperFoldStateManager)
31 
32 namespace {
33 const std::string g_FoldScreenRect = system::GetParameter("const.window.foldscreen.config_rect", "");
34 const int32_t PARAM_NUMBER_MIN = 10;
35 const int32_t HEIGHT_HALF = 2;
36 #ifdef TP_FEATURE_ENABLE
37 const int32_t TP_TYPE = 12;
38 const char* KEYBOARD_ON_CONFIG = "version:3+main";
39 const char* KEYBOARD_OFF_CONFIG = "version:3+whole";
40 #endif
41 static bool isHalfScreen_ = false;
42 static bool isHalfScreenSwitchOn_ = false;
43 static bool isHalfFolded_ = false;
44 static bool isKeyboardOn_ = false;
45 const std::string BOOTEVENT_BOOT_COMPLETED = "bootevent.boot.completed";
46 static sptr<FoldCreaseRegion> currentSuperFoldCreaseRegion_ = nullptr;
47 }
48 
DoAngleChangeFolded(SuperFoldStatusChangeEvents event)49 void SuperFoldStateManager::DoAngleChangeFolded(SuperFoldStatusChangeEvents event)
50 {
51     TLOGI(WmsLogTag::DMS, "enter %{public}d", event);
52     isHalfFolded_ = false;
53 }
54 
DoAngleChangeHalfFolded(SuperFoldStatusChangeEvents event)55 void SuperFoldStateManager::DoAngleChangeHalfFolded(SuperFoldStatusChangeEvents event)
56 {
57     TLOGI(WmsLogTag::DMS, "enter %{public}d", event);
58     isHalfFolded_ = true;
59     if (!isHalfScreenSwitchOn_) {
60         TLOGI(WmsLogTag::DMS, "Half Screen Switch is off");
61         return;
62     }
63     if (!ChangeScreenState(true)) {
64         TLOGI(WmsLogTag::DMS, "change to half screen fail!");
65     }
66 }
67 
DoAngleChangeExpanded(SuperFoldStatusChangeEvents event)68 void SuperFoldStateManager::DoAngleChangeExpanded(SuperFoldStatusChangeEvents event)
69 {
70     TLOGI(WmsLogTag::DMS, "enter %{public}d", event);
71     isHalfFolded_ = false;
72     if (isKeyboardOn_) {
73         TLOGI(WmsLogTag::DMS, "Keyboard On, no need to recover");
74         return;
75     }
76     if (!ChangeScreenState(false)) {
77         TLOGI(WmsLogTag::DMS, "recover from half screen fail!");
78     }
79 }
80 
DoKeyboardOn(SuperFoldStatusChangeEvents event)81 void SuperFoldStateManager::DoKeyboardOn(SuperFoldStatusChangeEvents event)
82 {
83     TLOGI(WmsLogTag::DMS, "enter %{public}d", event);
84     isKeyboardOn_ = true;
85     if (!ChangeScreenState(true)) {
86         TLOGI(WmsLogTag::DMS, "change to half screen fail!");
87     }
88 }
89 
DoKeyboardOff(SuperFoldStatusChangeEvents event)90 void SuperFoldStateManager::DoKeyboardOff(SuperFoldStatusChangeEvents event)
91 {
92     TLOGI(WmsLogTag::DMS, "enter %{public}d", event);
93     isKeyboardOn_ = false;
94     if (isHalfFolded_ && isHalfScreenSwitchOn_) {
95         TLOGI(WmsLogTag::DMS, "screen is folded and switch on, no need to recover");
96         return;
97     }
98     if (!ChangeScreenState(false)) {
99         TLOGI(WmsLogTag::DMS, "recover from half screen fail!");
100     }
101 }
102 
DoFoldedToHalfFolded(SuperFoldStatusChangeEvents event)103 void SuperFoldStateManager::DoFoldedToHalfFolded(SuperFoldStatusChangeEvents event)
104 {
105     TLOGI(WmsLogTag::DMS, "enter %{public}d", event);
106     isHalfFolded_ = true;
107     if (!isHalfScreenSwitchOn_) {
108         TLOGI(WmsLogTag::DMS, "Half Screen Switch is off");
109         return;
110     }
111     if (!ChangeScreenState(true)) {
112         TLOGI(WmsLogTag::DMS, "change to half screen fail!");
113     }
114 }
115 
InitSuperFoldStateManagerMap()116 void SuperFoldStateManager::InitSuperFoldStateManagerMap()
117 {
118     AddStateManagerMap(SuperFoldStatus::HALF_FOLDED,
119         SuperFoldStatusChangeEvents::ANGLE_CHANGE_EXPANDED,
120         SuperFoldStatus::EXPANDED,
121         &SuperFoldStateManager::DoAngleChangeExpanded);
122 
123     AddStateManagerMap(SuperFoldStatus::FOLDED,
124         SuperFoldStatusChangeEvents::ANGLE_CHANGE_HALF_FOLDED,
125         SuperFoldStatus::HALF_FOLDED,
126         &SuperFoldStateManager::DoFoldedToHalfFolded);
127 
128     AddStateManagerMap(SuperFoldStatus::FOLDED,
129         SuperFoldStatusChangeEvents::ANGLE_CHANGE_EXPANDED,
130         SuperFoldStatus::EXPANDED,
131         &SuperFoldStateManager::DoAngleChangeExpanded);
132 
133     AddStateManagerMap(SuperFoldStatus::EXPANDED,
134         SuperFoldStatusChangeEvents::ANGLE_CHANGE_HALF_FOLDED,
135         SuperFoldStatus::HALF_FOLDED,
136         &SuperFoldStateManager::DoAngleChangeHalfFolded);
137 
138     AddStateManagerMap(SuperFoldStatus::HALF_FOLDED,
139         SuperFoldStatusChangeEvents::ANGLE_CHANGE_FOLDED,
140         SuperFoldStatus::FOLDED,
141         &SuperFoldStateManager::DoAngleChangeFolded);
142 
143     AddStateManagerMap(SuperFoldStatus::HALF_FOLDED,
144         SuperFoldStatusChangeEvents::KEYBOARD_ON,
145         SuperFoldStatus::KEYBOARD,
146         &SuperFoldStateManager::DoKeyboardOn);
147 
148     AddStateManagerMap(SuperFoldStatus::KEYBOARD,
149         SuperFoldStatusChangeEvents::KEYBOARD_OFF,
150         SuperFoldStatus::HALF_FOLDED,
151         &SuperFoldStateManager::DoKeyboardOff);
152 
153     // 开机状态自检
154     AddStateManagerMap(SuperFoldStatus::UNKNOWN,
155         SuperFoldStatusChangeEvents::KEYBOARD_ON,
156         SuperFoldStatus::KEYBOARD,
157         [&](SuperFoldStatusChangeEvents events) {});
158 
159     AddStateManagerMap(SuperFoldStatus::UNKNOWN,
160         SuperFoldStatusChangeEvents::ANGLE_CHANGE_HALF_FOLDED,
161         SuperFoldStatus::HALF_FOLDED,
162         [&](SuperFoldStatusChangeEvents events) {});
163 
164     AddStateManagerMap(SuperFoldStatus::UNKNOWN,
165         SuperFoldStatusChangeEvents::ANGLE_CHANGE_EXPANDED,
166         SuperFoldStatus::EXPANDED,
167         [&](SuperFoldStatusChangeEvents events) {});
168 
169     AddStateManagerMap(SuperFoldStatus::UNKNOWN,
170         SuperFoldStatusChangeEvents::ANGLE_CHANGE_FOLDED,
171         SuperFoldStatus::FOLDED,
172         [&](SuperFoldStatusChangeEvents events) {});
173 }
174 
isParamsValid(std::vector<std::string> & params)175 bool SuperFoldStateManager::isParamsValid(std::vector<std::string>& params)
176 {
177     for (auto &param : params) {
178         if (param.size() == 0) {
179             return false;
180         }
181         for (int32_t i = 0; i < static_cast<int32_t>(param.size()); ++i) {
182             if (param.at(i) < '0' || param.at(i) > '9') {
183                 return false;
184             }
185         }
186     }
187     return true;
188 }
189 
InitSuperFoldCreaseRegionParams()190 void SuperFoldStateManager::InitSuperFoldCreaseRegionParams()
191 {
192     std::vector<std::string> foldRect = FoldScreenStateInternel::StringSplit(g_FoldScreenRect, ',');
193 
194     if (foldRect.empty() || foldRect.size() <= PARAM_NUMBER_MIN) {
195         // ccm numbers of parameter > 10
196         TLOGE(WmsLogTag::DMS, "foldRect is invalid");
197         return;
198     }
199 
200     if (!isParamsValid(foldRect)) {
201         TLOGE(WmsLogTag::DMS, "params is invalid");
202         return;
203     }
204 
205     ScreenId screenIdFull = 0;
206     int32_t superFoldCreaseRegionPosX = 0;
207     int32_t superFoldCreaseRegionPosY = std::stoi(foldRect[10]); // ccm PosY
208     int32_t superFoldCreaseRegionPosWidth = std::stoi(foldRect[4]); // ccm PosWidth
209     int32_t superFoldCreaseRegionPosHeight = std::stoi(foldRect[9]); // ccm PosHeight
210 
211     std::vector<DMRect> rect = {
212         {
213             superFoldCreaseRegionPosX, superFoldCreaseRegionPosY,
214             superFoldCreaseRegionPosWidth, superFoldCreaseRegionPosHeight
215         }
216     };
217     currentSuperFoldCreaseRegion_ = new FoldCreaseRegion(screenIdFull, rect);
218 }
219 
SuperFoldStateManager()220 SuperFoldStateManager::SuperFoldStateManager()
221 {
222     InitSuperFoldStateManagerMap();
223     InitSuperFoldCreaseRegionParams();
224     WatchParameter(BOOTEVENT_BOOT_COMPLETED.c_str(), BootFinishedCallback, this);
225 }
226 
~SuperFoldStateManager()227 SuperFoldStateManager::~SuperFoldStateManager()
228 {
229     UnregisterHalfScreenSwitchesObserver();
230 }
231 
AddStateManagerMap(SuperFoldStatus curState,SuperFoldStatusChangeEvents event,SuperFoldStatus nextState,std::function<void (SuperFoldStatusChangeEvents)> action)232 void SuperFoldStateManager::AddStateManagerMap(SuperFoldStatus curState,
233     SuperFoldStatusChangeEvents event,
234     SuperFoldStatus nextState,
235     std::function<void (SuperFoldStatusChangeEvents)> action)
236 {
237     stateManagerMap_[{curState, event}] = {nextState, action};
238 }
239 
TransferState(SuperFoldStatus nextState)240 void SuperFoldStateManager::TransferState(SuperFoldStatus nextState)
241 {
242     TLOGI(WmsLogTag::DMS, "TransferState from %{public}d to %{public}d", curState_.load(), nextState);
243     curState_ .store(nextState);
244 }
245 
MatchSuperFoldStatusToFoldStatus(SuperFoldStatus superFoldStatus)246 FoldStatus SuperFoldStateManager::MatchSuperFoldStatusToFoldStatus(SuperFoldStatus superFoldStatus)
247 {
248     switch (superFoldStatus) {
249         case SuperFoldStatus::EXPANDED:
250             return FoldStatus::EXPAND;
251         case SuperFoldStatus::HALF_FOLDED:
252             return FoldStatus::HALF_FOLD;
253         case SuperFoldStatus::FOLDED:
254             return FoldStatus::FOLDED;
255         case SuperFoldStatus::KEYBOARD:
256             return FoldStatus::HALF_FOLD;
257         default:
258             return FoldStatus::UNKNOWN;
259     }
260 }
261 
ReportNotifySuperFoldStatusChange(int32_t currentStatus,int32_t nextStatus,float postureAngle)262 void SuperFoldStateManager::ReportNotifySuperFoldStatusChange(int32_t currentStatus, int32_t nextStatus,
263     float postureAngle)
264 {
265     TLOGI(WmsLogTag::DMS, "currentStatus: %{public}d, nextStatus: %{public}d, postureAngle: %{public}f",
266         currentStatus, nextStatus, postureAngle);
267     int32_t ret = HiSysEventWrite(
268         OHOS::HiviewDFX::HiSysEvent::Domain::WINDOW_MANAGER,
269         "NOTIFY_FOLD_STATE_CHANGE",
270         OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR,
271         "CURRENT_FOLD_STATUS", currentStatus,
272         "NEXT_FOLD_STATUS", nextStatus,
273         "SENSOR_POSTURE", postureAngle);
274     if (ret != 0) {
275         TLOGI(WmsLogTag::DMS, "Write HiSysEvent error, ret: %{public}d", ret);
276     }
277 }
278 
HandleSuperFoldStatusChange(SuperFoldStatusChangeEvents event)279 void SuperFoldStateManager::HandleSuperFoldStatusChange(SuperFoldStatusChangeEvents event)
280 {
281     SuperFoldStatus curState = curState_.load();
282     SuperFoldStatus nextState = SuperFoldStatus::UNKNOWN;
283     bool isTransfer = false;
284     std::function<void (SuperFoldStatusChangeEvents)> action;
285 
286     auto item = stateManagerMap_.find({curState, event});
287     if (item != stateManagerMap_.end()) {
288         nextState = item->second.nextState;
289         action = item->second.action;
290         isTransfer = true;
291     }
292 
293     float curAngle = SuperFoldSensorManager::GetInstance().GetCurAngle();
294     TLOGD(WmsLogTag::DMS, "curAngle: %{public}f", curAngle);
295     if (isTransfer && action) {
296         HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "ssm:HandleSuperFoldStatusChange");
297         ReportNotifySuperFoldStatusChange(static_cast<int32_t>(curState), static_cast<int32_t>(nextState), curAngle);
298         action(event);
299         TransferState(nextState);
300         HandleDisplayNotify(event);
301         // notify
302         auto screenSession = ScreenSessionManager::GetInstance().GetDefaultScreenSession();
303         if (screenSession == nullptr) {
304             TLOGE(WmsLogTag::DMS, "screen session is null!");
305             return;
306         }
307         ScreenId screenId = screenSession->GetScreenId();
308         if (isHalfScreen_) {
309             ScreenSessionManager::GetInstance().OnSuperFoldStatusChange(screenId, SuperFoldStatus::KEYBOARD);
310         } else {
311             ScreenSessionManager::GetInstance().OnSuperFoldStatusChange(screenId, curState_.load());
312         }
313         ScreenSessionManager::GetInstance().NotifyFoldStatusChanged(
314             MatchSuperFoldStatusToFoldStatus(curState_.load()));
315     }
316 }
317 
GetCurrentStatus()318 SuperFoldStatus SuperFoldStateManager::GetCurrentStatus()
319 {
320     if (isHalfScreen_) {
321         return SuperFoldStatus::KEYBOARD;
322     }
323     return curState_.load();
324 }
325 
SetCurrentStatus(SuperFoldStatus curState)326 void SuperFoldStateManager::SetCurrentStatus(SuperFoldStatus curState)
327 {
328     curState_.store(curState);
329 }
330 
GetCurrentFoldCreaseRegion()331 sptr<FoldCreaseRegion> SuperFoldStateManager::GetCurrentFoldCreaseRegion()
332 {
333     TLOGI(WmsLogTag::DMS, "GetCurrentFoldCreaseRegion()");
334     return currentSuperFoldCreaseRegion_;
335 }
336 
HandleDisplayNotify(SuperFoldStatusChangeEvents changeEvent)337 void SuperFoldStateManager::HandleDisplayNotify(SuperFoldStatusChangeEvents changeEvent)
338 {
339     TLOGI(WmsLogTag::DMS, "changeEvent: %{public}d", static_cast<uint32_t>(changeEvent));
340     sptr<ScreenSession> screenSession =
341         ScreenSessionManager::GetInstance().GetDefaultScreenSession();
342     if (screenSession == nullptr) {
343         TLOGE(WmsLogTag::DMS, "screen session is null");
344         return;
345     }
346     if (screenSession->GetFakeScreenSession() == nullptr) {
347         TLOGE(WmsLogTag::DMS, "fake screen session is null");
348         return;
349     }
350     switch (changeEvent) {
351         case SuperFoldStatusChangeEvents::ANGLE_CHANGE_HALF_FOLDED:
352             HandleExtendToHalfFoldDisplayNotify(screenSession);
353             TLOGI(WmsLogTag::DMS, "handle extend change to half fold");
354             break;
355         case SuperFoldStatusChangeEvents::ANGLE_CHANGE_EXPANDED:
356             HandleHalfFoldToExtendDisplayNotify(screenSession);
357             TLOGI(WmsLogTag::DMS, "handle half fold change to extend");
358             break;
359         case SuperFoldStatusChangeEvents::KEYBOARD_ON:
360             HandleKeyboardOnDisplayNotify(screenSession);
361             TLOGI(WmsLogTag::DMS, "handle keyboard on");
362             break;
363         case SuperFoldStatusChangeEvents::KEYBOARD_OFF:
364             HandleKeyboardOffDisplayNotify(screenSession);
365             TLOGI(WmsLogTag::DMS, "handle keyboard off");
366             break;
367         case SuperFoldStatusChangeEvents::SYSTEM_KEYBOARD_ON:
368             HandleSystemKeyboardStatusDisplayNotify(screenSession, true);
369             TLOGI(WmsLogTag::DMS, "handle system keyboard on");
370             break;
371         case SuperFoldStatusChangeEvents::SYSTEM_KEYBOARD_OFF:
372             HandleSystemKeyboardStatusDisplayNotify(screenSession, false);
373             TLOGI(WmsLogTag::DMS, "handle system keyboard off");
374             break;
375         default:
376             TLOGE(WmsLogTag::DMS, "nothing to handle");
377             return;
378     }
379 }
380 
HandleExtendToHalfFoldDisplayNotify(sptr<ScreenSession> screenSession)381 void SuperFoldStateManager::HandleExtendToHalfFoldDisplayNotify(sptr<ScreenSession> screenSession)
382 {
383     screenSession->UpdatePropertyByFakeInUse(true);
384     screenSession->SetIsBScreenHalf(true);
385     auto screenWidth = screenSession->GetScreenProperty().GetBounds().rect_.GetWidth();
386     auto screenHeight = screenSession->GetScreenProperty().GetBounds().rect_.GetHeight();
387     if (screenWidth > screenHeight) {
388         TLOGW(WmsLogTag::DMS, "not vertical, swap width and height");
389         screenSession->UpdatePropertyByResolution(screenHeight, screenWidth);
390     }
391     ScreenSessionManager::GetInstance().NotifyDisplayChanged(
392         screenSession->ConvertToDisplayInfo(), DisplayChangeEvent::SUPER_FOLD_RESOLUTION_CHANGED);
393     sptr<ScreenSession> fakeScreenSession = screenSession->GetFakeScreenSession();
394     ScreenSessionManager::GetInstance().NotifyDisplayCreate(
395         fakeScreenSession->ConvertToDisplayInfo());
396     screenSession->PropertyChange(screenSession->GetScreenProperty(),
397         ScreenPropertyChangeReason::SUPER_FOLD_STATUS_CHANGE);
398 }
399 
HandleHalfFoldToExtendDisplayNotify(sptr<ScreenSession> screenSession)400 void SuperFoldStateManager::HandleHalfFoldToExtendDisplayNotify(sptr<ScreenSession> screenSession)
401 {
402     screenSession->UpdatePropertyByFakeInUse(false);
403     screenSession->SetIsBScreenHalf(false);
404     sptr<ScreenSession> fakeScreenSession = screenSession->GetFakeScreenSession();
405     sptr<DisplayInfo> fakeDisplayInfo = fakeScreenSession->ConvertToDisplayInfo();
406     if (fakeDisplayInfo == nullptr) {
407         TLOGE(WmsLogTag::DMS, "get fake display failed");
408         return;
409     }
410     DisplayId fakeDisplayId = fakeDisplayInfo->GetDisplayId();
411     ScreenSessionManager::GetInstance().NotifyDisplayDestroy(fakeDisplayId);
412     ScreenSessionManager::GetInstance().NotifyDisplayChanged(
413         screenSession->ConvertToDisplayInfo(),
414         DisplayChangeEvent::SUPER_FOLD_RESOLUTION_CHANGED);
415     screenSession->PropertyChange(screenSession->GetScreenProperty(),
416         ScreenPropertyChangeReason::SUPER_FOLD_STATUS_CHANGE);
417 }
418 
HandleKeyboardOnDisplayNotify(sptr<ScreenSession> screenSession)419 void SuperFoldStateManager::HandleKeyboardOnDisplayNotify(sptr<ScreenSession> screenSession)
420 {
421     HandleHalfScreenDisplayNotify(screenSession);
422 }
423 
HandleHalfScreenDisplayNotify(sptr<ScreenSession> screenSession)424 void SuperFoldStateManager::HandleHalfScreenDisplayNotify(sptr<ScreenSession> screenSession)
425 {
426     auto screeBounds = screenSession->GetScreenProperty().GetBounds();
427     screenSession->UpdatePropertyByFakeInUse(false);
428     screenSession->SetIsBScreenHalf(true);
429     int32_t validheight = GetCurrentValidHeight(screenSession);
430     if (screeBounds.rect_.GetWidth() < screeBounds.rect_.GetHeight()) {
431         screenSession->SetValidHeight(validheight);
432         screenSession->SetValidWidth(screeBounds.rect_.GetWidth());
433     } else {
434         screenSession->SetValidWidth(screeBounds.rect_.GetHeight());
435         screenSession->SetValidHeight(validheight);
436     }
437     sptr<ScreenSession> fakeScreenSession = screenSession->GetFakeScreenSession();
438     sptr<DisplayInfo> fakeDisplayInfo = fakeScreenSession->ConvertToDisplayInfo();
439     if (fakeDisplayInfo == nullptr) {
440         TLOGE(WmsLogTag::DMS, "get fake display failed");
441         return;
442     }
443     DisplayId fakeDisplayId = fakeDisplayInfo->GetDisplayId();
444     ScreenSessionManager::GetInstance().NotifyDisplayDestroy(fakeDisplayId);
445     screenSession->PropertyChange(screenSession->GetScreenProperty(),
446         ScreenPropertyChangeReason::SUPER_FOLD_STATUS_CHANGE);
447     ScreenSessionManager::GetInstance().UpdateValidArea(
448         screenSession->GetScreenId(),
449         screenSession->GetValidWidth(),
450         screenSession->GetValidHeight());
451 }
452 
HandleKeyboardOffDisplayNotify(sptr<ScreenSession> screenSession)453 void SuperFoldStateManager::HandleKeyboardOffDisplayNotify(sptr<ScreenSession> screenSession)
454 {
455     if (isHalfScreen_) {
456         TLOGI(WmsLogTag::DMS, "current is half screen");
457         return;
458     }
459     HandleFullScreenDisplayNotify(screenSession);
460 }
461 
HandleFullScreenDisplayNotify(sptr<ScreenSession> screenSession)462 void SuperFoldStateManager::HandleFullScreenDisplayNotify(sptr<ScreenSession> screenSession)
463 {
464     auto screeBounds = screenSession->GetScreenProperty().GetBounds();
465     screenSession->UpdatePropertyByFakeInUse(true);
466     screenSession->SetIsBScreenHalf(true);
467     screenSession->SetValidHeight(screeBounds.rect_.GetHeight());
468     sptr<ScreenSession> fakeScreenSession = screenSession->GetFakeScreenSession();
469     ScreenSessionManager::GetInstance().NotifyDisplayCreate(
470         fakeScreenSession->ConvertToDisplayInfo());
471     screenSession->PropertyChange(screenSession->GetScreenProperty(),
472         ScreenPropertyChangeReason::SUPER_FOLD_STATUS_CHANGE);
473     ScreenSessionManager::GetInstance().UpdateValidArea(
474         screenSession->GetScreenId(),
475         screenSession->GetValidWidth(),
476         screenSession->GetValidHeight());
477 }
478 
SetSystemKeyboardStatus(bool isOn)479 void SuperFoldStateManager::SetSystemKeyboardStatus(bool isOn)
480 {
481     SuperFoldStatusChangeEvents events = isOn ? SuperFoldStatusChangeEvents::SYSTEM_KEYBOARD_ON
482         : SuperFoldStatusChangeEvents::SYSTEM_KEYBOARD_OFF;
483     HandleDisplayNotify(events);
484 }
485 
HandleSystemKeyboardStatusDisplayNotify(sptr<ScreenSession> screenSession,bool isOn)486 void SuperFoldStateManager::HandleSystemKeyboardStatusDisplayNotify(
487     sptr<ScreenSession> screenSession, bool isOn)
488 {
489     screenSession->UpdatePropertyByFakeInUse(!isOn);
490     screenSession->SetIsBScreenHalf(true);
491     sptr<ScreenSession> fakeScreenSession = screenSession->GetFakeScreenSession();
492     sptr<DisplayInfo> fakeDisplayInfo = fakeScreenSession->ConvertToDisplayInfo();
493     if (fakeDisplayInfo == nullptr) {
494         TLOGE(WmsLogTag::DMS, "get fake display failed");
495         return;
496     }
497     if (isOn) {
498         DisplayId fakeDisplayId = fakeDisplayInfo->GetDisplayId();
499         ScreenSessionManager::GetInstance().NotifyDisplayDestroy(fakeDisplayId);
500 
501         auto screeBounds = screenSession->GetScreenProperty().GetBounds();
502         int32_t validheight = GetCurrentValidHeight(screenSession);
503         if (screeBounds.rect_.GetWidth() < screeBounds.rect_.GetHeight()) {
504             screenSession->SetPointerActiveWidth(static_cast<uint32_t>(screeBounds.rect_.GetWidth()));
505             screenSession->SetPointerActiveHeight(static_cast<uint32_t>(validheight));
506         } else {
507             screenSession->SetPointerActiveWidth(static_cast<uint32_t>(screeBounds.rect_.GetHeight()));
508             screenSession->SetPointerActiveHeight(static_cast<uint32_t>(validheight));
509         }
510         TLOGD(WmsLogTag::DMS, "vh: %{public}d, paw: %{public}u, pah: %{public}u", validheight,
511             screenSession->GetPointerActiveWidth(), screenSession->GetPointerActiveHeight());
512     } else {
513         SuperFoldStatus curFoldState = ScreenSessionManager::GetInstance().GetSuperFoldStatus();
514         if (curFoldState == SuperFoldStatus::HALF_FOLDED) {
515             ScreenSessionManager::GetInstance().NotifyDisplayCreate(fakeDisplayInfo);
516         }
517 
518         screenSession->SetPointerActiveWidth(0);
519         screenSession->SetPointerActiveHeight(0);
520         TLOGD(WmsLogTag::DMS, "paw: %{public}u, pah: %{public}u",
521             screenSession->GetPointerActiveWidth(), screenSession->GetPointerActiveHeight());
522     }
523     screenSession->PropertyChange(screenSession->GetScreenProperty(),
524         ScreenPropertyChangeReason::SUPER_FOLD_STATUS_CHANGE);
525 }
526 
GetCurrentValidHeight(sptr<ScreenSession> screenSession)527 int32_t SuperFoldStateManager::GetCurrentValidHeight(sptr<ScreenSession> screenSession)
528 {
529     if (currentSuperFoldCreaseRegion_ != nullptr) {
530         std::vector<DMRect> creaseRects = currentSuperFoldCreaseRegion_->GetCreaseRects();
531         if (!creaseRects.empty()) {
532             TLOGI(WmsLogTag::DMS, "validheight: %{public}d", creaseRects[0].posY_);
533             return creaseRects[0].posY_;
534         }
535     }
536     TLOGE(WmsLogTag::DMS, "Get CreaseRects failed, validheight is half of height");
537     auto screeBounds = screenSession->GetScreenProperty().GetBounds();
538     if (screeBounds.rect_.GetWidth() < screeBounds.rect_.GetHeight()) {
539         return screeBounds.rect_.GetHeight() / HEIGHT_HALF;
540     } else {
541         return screeBounds.rect_.GetWidth() / HEIGHT_HALF;
542     }
543 }
544 
BootFinishedCallback(const char * key,const char * value,void * context)545 void SuperFoldStateManager::BootFinishedCallback(const char *key, const char *value, void *context)
546 {
547     if (strcmp(key, BOOTEVENT_BOOT_COMPLETED.c_str()) == 0 && strcmp(value, "true") == 0) {
548         TLOGI(WmsLogTag::DMS, "boot animation finished");
549         auto &that = *reinterpret_cast<SuperFoldStateManager *>(context);
550         that.RegisterHalfScreenSwitchesObserver();
551         that.InitHalfScreen();
552     }
553 }
554 
InitHalfScreen()555 void SuperFoldStateManager::InitHalfScreen()
556 {
557     isHalfScreenSwitchOn_ = ScreenSettingHelper::GetHalfScreenSwitchState();
558     SuperFoldStatus curFoldState = ScreenSessionManager::GetInstance().GetSuperFoldStatus();
559     if (curFoldState == SuperFoldStatus::HALF_FOLDED) {
560         isHalfFolded_ = true;
561     }
562     if (isHalfScreenSwitchOn_ && isHalfFolded_) {
563         if (!ChangeScreenState(true)) {
564             TLOGI(WmsLogTag::DMS, "change to half screen fail!");
565         }
566         auto screenSession = ScreenSessionManager::GetInstance().GetDefaultScreenSession();
567         ScreenId screenId = screenSession->GetScreenId();
568         ScreenSessionManager::GetInstance().OnSuperFoldStatusChange(screenId, SuperFoldStatus::KEYBOARD);
569     }
570 }
571 
RegisterHalfScreenSwitchesObserver()572 void SuperFoldStateManager::RegisterHalfScreenSwitchesObserver()
573 {
574     TLOGI(WmsLogTag::DMS, "half screen switch register");
575     SettingObserver::UpdateFunc updateFunc =
576         [&](const std::string& key) {this->OnHalfScreenSwitchesStateChanged();};
577     ScreenSettingHelper::RegisterSettingHalfScreenObserver(updateFunc);
578 }
579 
UnregisterHalfScreenSwitchesObserver()580 void SuperFoldStateManager::UnregisterHalfScreenSwitchesObserver()
581 {
582     TLOGI(WmsLogTag::DMS, "half screen switch unregister");
583     ScreenSettingHelper::UnregisterSettingHalfScreenObserver();
584 }
585 
OnHalfScreenSwitchesStateChanged()586 void SuperFoldStateManager::OnHalfScreenSwitchesStateChanged()
587 {
588     TLOGI(WmsLogTag::DMS, "half screen switch state changed");
589     bool curSwitchState = ScreenSettingHelper::GetHalfScreenSwitchState();
590     if (curSwitchState == isHalfScreenSwitchOn_) {
591         TLOGI(WmsLogTag::DMS, "half screen switch didn't change");
592         return;
593     }
594     isHalfScreenSwitchOn_ = curSwitchState;
595     auto tempState = SuperFoldStatus::KEYBOARD;
596     if ((isHalfScreenSwitchOn_ && isHalfFolded_) || isKeyboardOn_)  {
597         if (!ChangeScreenState(true)) {
598             TLOGI(WmsLogTag::DMS, "change to half screen fail!");
599         }
600     } else {
601         if (!ChangeScreenState(false)) {
602             TLOGI(WmsLogTag::DMS, "recover from half screen fail!");
603         }
604         tempState = curState_;
605     }
606     auto screenSession = ScreenSessionManager::GetInstance().GetDefaultScreenSession();
607     ScreenId screenId = screenSession->GetScreenId();
608     ScreenSessionManager::GetInstance().OnSuperFoldStatusChange(screenId, tempState);
609 }
610 
ChangeScreenState(bool toHalf)611 bool SuperFoldStateManager::ChangeScreenState(bool toHalf)
612 {
613     ScreenSessionManager::GetInstance().NotifyScreenMagneticStateChanged(toHalf);
614     TLOGD(WmsLogTag::DMS, "isHalfScreen_ = %{public}d, toHalf = %{public}d", isHalfScreen_, toHalf);
615     if (isHalfScreen_ == toHalf) {
616         TLOGI(WmsLogTag::DMS, "screen is already in the desired state, no need to change");
617         return false;
618     }
619     sptr<ScreenSession> screenSession = ScreenSessionManager::GetInstance().
620         GetDefaultScreenSession();
621     if (screenSession == nullptr) {
622         TLOGE(WmsLogTag::DMS, "screen session is null!");
623         return false;
624     }
625     auto screenProperty = screenSession->GetScreenProperty();
626     auto screenWidth = screenProperty.GetPhyBounds().rect_.GetWidth();
627     auto screenHeight = screenProperty.GetPhyBounds().rect_.GetHeight();
628     if (toHalf) {
629         screenWidth = screenProperty.GetPhyBounds().rect_.GetWidth();
630         screenHeight = screenProperty.GetPhyBounds().rect_.GetHeight() / HEIGHT_HALF;
631         HandleHalfScreenDisplayNotify(screenSession);
632     } else {
633         HandleFullScreenDisplayNotify(screenSession);
634     }
635     OHOS::Rect rectCur{
636         .x = 0,
637         .y = 0,
638         .w = static_cast<int>(screenWidth),
639         .h = static_cast<int>(screenHeight),
640     };
641     // SCREEN_ID_FULL = 0
642     auto response = RSInterfaces::GetInstance().SetScreenActiveRect(0, rectCur);
643     isHalfScreen_ = toHalf;
644 #ifdef TP_FEATURE_ENABLE
645     RSInterfaces::GetInstance().SetTpFeatureConfig(TP_TYPE,
646         toHalf ? KEYBOARD_ON_CONFIG : KEYBOARD_OFF_CONFIG, TpFeatureConfigType::AFT_TP_FEATURE);
647 #endif
648     TLOGI(WmsLogTag::DMS, "rect [%{public}f , %{public}f], rs response is %{public}ld",
649         screenWidth, screenHeight, static_cast<long>(response));
650     return true;
651 }
652 } // Rosen
653 } // OHOS