• 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 
24 namespace OHOS {
25 
26 namespace Rosen {
27 
28 WM_IMPLEMENT_SINGLE_INSTANCE(SuperFoldStateManager)
29 
30 namespace {
31 const std::string g_FoldScreenRect = system::GetParameter("const.window.foldscreen.config_rect", "");
32 constexpr uint32_t DEFAULT_FOLD_REGION_HEIGHT = 82; // default height of pivot area
33 const int32_t PARAM_NUMBER_MIN = 10;
34 const int32_t HEIGHT_HALF = 2;
35 #ifdef TP_FEATURE_ENABLE
36 const int32_t TP_TYPE = 12;
37 const char* KEYBOARD_ON_CONFIG = "version:3+main";
38 const char* KEYBOARD_OFF_CONFIG = "version:3+whole";
39 #endif
40 static bool isKeyboardOn_ = false;
41 static bool isSystemKeyboardOn_ = false;
42 constexpr int32_t FOLD_CREASE_RECT_SIZE = 4; //numbers of parameter on the current device is 4
43 const std::string g_LiveCreaseRegion = system::GetParameter("const.display.foldscreen.crease_region", "");
44 const std::string FOLD_CREASE_DELIMITER = ",;";
45 constexpr ScreenId SCREEN_ID_FULL = 0;
46 const int32_t SCREEN_WIDTH_INDEX = 2;
47 const int32_t CREASE_WIDTH_INDEX = 3;
48 }
49 
DoAngleChangeFolded(SuperFoldStatusChangeEvents event)50 void SuperFoldStateManager::DoAngleChangeFolded(SuperFoldStatusChangeEvents event)
51 {
52     TLOGI(WmsLogTag::DMS, "enter %{public}d", event);
53 }
54 
DoAngleChangeHalfFolded(SuperFoldStatusChangeEvents event)55 void SuperFoldStateManager::DoAngleChangeHalfFolded(SuperFoldStatusChangeEvents event)
56 {
57     TLOGI(WmsLogTag::DMS, "enter %{public}d", event);
58 }
59 
DoAngleChangeExpanded(SuperFoldStatusChangeEvents event)60 void SuperFoldStateManager::DoAngleChangeExpanded(SuperFoldStatusChangeEvents event)
61 {
62     TLOGI(WmsLogTag::DMS, "enter %{public}d", event);
63 }
64 
DoKeyboardOn(SuperFoldStatusChangeEvents event)65 void SuperFoldStateManager::DoKeyboardOn(SuperFoldStatusChangeEvents event)
66 {
67     TLOGI(WmsLogTag::DMS, "enter %{public}d", event);
68     isKeyboardOn_ = true;
69     if (!ChangeScreenState(true)) {
70         TLOGI(WmsLogTag::DMS, "change to half screen fail!");
71     }
72 }
73 
DoKeyboardOff(SuperFoldStatusChangeEvents event)74 void SuperFoldStateManager::DoKeyboardOff(SuperFoldStatusChangeEvents event)
75 {
76     TLOGI(WmsLogTag::DMS, "enter %{public}d", event);
77     isKeyboardOn_ = false;
78     if (!ChangeScreenState(false)) {
79         TLOGI(WmsLogTag::DMS, "recover from half screen fail!");
80     }
81 }
82 
DoFoldedToHalfFolded(SuperFoldStatusChangeEvents event)83 void SuperFoldStateManager::DoFoldedToHalfFolded(SuperFoldStatusChangeEvents event)
84 {
85     TLOGI(WmsLogTag::DMS, "enter %{public}d", event);
86 }
87 
InitSuperFoldStateManagerMap()88 void SuperFoldStateManager::InitSuperFoldStateManagerMap()
89 {
90     AddStateManagerMap(SuperFoldStatus::HALF_FOLDED,
91         SuperFoldStatusChangeEvents::ANGLE_CHANGE_EXPANDED,
92         SuperFoldStatus::EXPANDED,
93         &SuperFoldStateManager::DoAngleChangeExpanded);
94 
95     AddStateManagerMap(SuperFoldStatus::FOLDED,
96         SuperFoldStatusChangeEvents::ANGLE_CHANGE_HALF_FOLDED,
97         SuperFoldStatus::HALF_FOLDED,
98         &SuperFoldStateManager::DoFoldedToHalfFolded);
99 
100     AddStateManagerMap(SuperFoldStatus::FOLDED,
101         SuperFoldStatusChangeEvents::ANGLE_CHANGE_EXPANDED,
102         SuperFoldStatus::EXPANDED,
103         &SuperFoldStateManager::DoAngleChangeExpanded);
104 
105     AddStateManagerMap(SuperFoldStatus::EXPANDED,
106         SuperFoldStatusChangeEvents::ANGLE_CHANGE_HALF_FOLDED,
107         SuperFoldStatus::HALF_FOLDED,
108         &SuperFoldStateManager::DoAngleChangeHalfFolded);
109 
110     AddStateManagerMap(SuperFoldStatus::HALF_FOLDED,
111         SuperFoldStatusChangeEvents::ANGLE_CHANGE_FOLDED,
112         SuperFoldStatus::FOLDED,
113         &SuperFoldStateManager::DoAngleChangeFolded);
114 
115     AddStateManagerMap(SuperFoldStatus::HALF_FOLDED,
116         SuperFoldStatusChangeEvents::KEYBOARD_ON,
117         SuperFoldStatus::KEYBOARD,
118         &SuperFoldStateManager::DoKeyboardOn);
119 
120     AddStateManagerMap(SuperFoldStatus::KEYBOARD,
121         SuperFoldStatusChangeEvents::KEYBOARD_OFF,
122         SuperFoldStatus::HALF_FOLDED,
123         &SuperFoldStateManager::DoKeyboardOff);
124 
125     // 开机状态自检
126     AddStateManagerMap(SuperFoldStatus::UNKNOWN,
127         SuperFoldStatusChangeEvents::KEYBOARD_ON,
128         SuperFoldStatus::KEYBOARD,
129         [&](SuperFoldStatusChangeEvents events) {});
130 
131     AddStateManagerMap(SuperFoldStatus::UNKNOWN,
132         SuperFoldStatusChangeEvents::ANGLE_CHANGE_HALF_FOLDED,
133         SuperFoldStatus::HALF_FOLDED,
134         [&](SuperFoldStatusChangeEvents events) {});
135 
136     AddStateManagerMap(SuperFoldStatus::UNKNOWN,
137         SuperFoldStatusChangeEvents::ANGLE_CHANGE_EXPANDED,
138         SuperFoldStatus::EXPANDED,
139         [&](SuperFoldStatusChangeEvents events) {});
140 
141     AddStateManagerMap(SuperFoldStatus::UNKNOWN,
142         SuperFoldStatusChangeEvents::ANGLE_CHANGE_FOLDED,
143         SuperFoldStatus::FOLDED,
144         [&](SuperFoldStatusChangeEvents events) {});
145 }
146 
isParamsValid(std::vector<std::string> & params)147 bool SuperFoldStateManager::isParamsValid(std::vector<std::string>& params)
148 {
149     for (auto &param : params) {
150         if (param.size() == 0) {
151             return false;
152         }
153         for (int32_t i = 0; i < static_cast<int32_t>(param.size()); ++i) {
154             if (param.at(i) < '0' || param.at(i) > '9') {
155                 return false;
156             }
157         }
158     }
159     return true;
160 }
161 
InitSuperFoldCreaseRegionParams()162 void SuperFoldStateManager::InitSuperFoldCreaseRegionParams()
163 {
164     std::vector<std::string> foldRect = FoldScreenStateInternel::StringSplit(g_FoldScreenRect, ',');
165 
166     if (foldRect.empty() || foldRect.size() <= PARAM_NUMBER_MIN) {
167         // ccm numbers of parameter > 10
168         TLOGE(WmsLogTag::DMS, "foldRect is invalid");
169         return;
170     }
171 
172     if (!isParamsValid(foldRect)) {
173         TLOGE(WmsLogTag::DMS, "params is invalid");
174         return;
175     }
176 
177     ScreenId screenIdFull = 0;
178     int32_t superFoldCreaseRegionPosX = 0;
179     int32_t superFoldCreaseRegionPosY = std::stoi(foldRect[10]); // ccm PosY
180     int32_t superFoldCreaseRegionPosWidth = std::stoi(foldRect[4]); // ccm PosWidth
181     int32_t superFoldCreaseRegionPosHeight = std::stoi(foldRect[9]); // ccm PosHeight
182 
183     std::vector<DMRect> rect = {
184         {
185             superFoldCreaseRegionPosX, superFoldCreaseRegionPosY,
186             superFoldCreaseRegionPosWidth, superFoldCreaseRegionPosHeight
187         }
188     };
189     currentSuperFoldCreaseRegion_ = new FoldCreaseRegion(screenIdFull, rect);
190 }
191 
GetFoldCreaseRegion(bool isVertical,bool isNeedReverse) const192 FoldCreaseRegion SuperFoldStateManager::GetFoldCreaseRegion(bool isVertical, bool isNeedReverse) const
193 {
194     std::vector<int32_t> foldRect = FoldScreenStateInternel::StringFoldRectSplitToInt(g_LiveCreaseRegion,
195         FOLD_CREASE_DELIMITER);
196     if (foldRect.size() != FOLD_CREASE_RECT_SIZE) {
197         TLOGE(WmsLogTag::DMS, "foldRect is invalid");
198         return FoldCreaseRegion(0, {});
199     }
200 
201     ScreenId screenIdFull = 0;
202     std::vector<DMRect> foldCreaseRect;
203     GetFoldCreaseRect(isVertical, isNeedReverse, foldRect, foldCreaseRect);
204     return FoldCreaseRegion(screenIdFull, foldCreaseRect);
205 }
206 
GetFoldCreaseRect(bool isVertical,bool isNeedReverse,const std::vector<int32_t> & foldRect,std::vector<DMRect> & foldCreaseRect) const207 void SuperFoldStateManager::GetFoldCreaseRect(bool isVertical, bool isNeedReverse,
208     const std::vector<int32_t>& foldRect, std::vector<DMRect>& foldCreaseRect) const
209 {
210     int32_t liveCreaseRegionPosX; // live Crease Region PosX
211     int32_t liveCreaseRegionPosY; // live Crease Region PosY
212     uint32_t liveCreaseRegionPosWidth; // live Crease Region PosWidth
213     uint32_t liveCreaseRegionPosHeight; // live Crease Region PosHeight
214     int32_t curLeft = foldRect[0];
215     int32_t curTop = foldRect[1];
216     uint32_t screenWidth = static_cast<uint32_t>(foldRect[SCREEN_WIDTH_INDEX]);
217     uint32_t creaseWidth = static_cast<uint32_t>(foldRect[CREASE_WIDTH_INDEX]);
218     if (isNeedReverse) {
219         auto screenProperty = ScreenSessionManager::GetInstance().GetPhyScreenProperty(SCREEN_ID_FULL);
220         curTop = screenProperty.GetPhyBounds().rect_.GetHeight() - curTop - creaseWidth;
221     }
222     if (isVertical) {
223         TLOGI(WmsLogTag::DMS, "the current FoldCreaseRect is vertical");
224         liveCreaseRegionPosX = curTop;
225         liveCreaseRegionPosY = curLeft;
226         liveCreaseRegionPosWidth = creaseWidth;
227         liveCreaseRegionPosHeight = screenWidth;
228     } else {
229         TLOGI(WmsLogTag::DMS, "the current FoldCreaseRect is horizontal");
230         liveCreaseRegionPosX = curLeft;
231         liveCreaseRegionPosY = curTop;
232         liveCreaseRegionPosWidth = screenWidth;
233         liveCreaseRegionPosHeight = creaseWidth;
234     }
235     foldCreaseRect = {
236         {
237             liveCreaseRegionPosX, liveCreaseRegionPosY,
238             liveCreaseRegionPosWidth, liveCreaseRegionPosHeight
239         }
240     };
241     return;
242 }
243 
SuperFoldStateManager()244 SuperFoldStateManager::SuperFoldStateManager()
245 {
246     InitSuperFoldStateManagerMap();
247     InitSuperFoldCreaseRegionParams();
248 }
249 
~SuperFoldStateManager()250 SuperFoldStateManager::~SuperFoldStateManager()
251 {
252 }
253 
AddStateManagerMap(SuperFoldStatus curState,SuperFoldStatusChangeEvents event,SuperFoldStatus nextState,std::function<void (SuperFoldStatusChangeEvents)> action)254 void SuperFoldStateManager::AddStateManagerMap(SuperFoldStatus curState,
255     SuperFoldStatusChangeEvents event,
256     SuperFoldStatus nextState,
257     std::function<void (SuperFoldStatusChangeEvents)> action)
258 {
259     stateManagerMap_[{curState, event}] = {nextState, action};
260 }
261 
TransferState(SuperFoldStatus nextState)262 void SuperFoldStateManager::TransferState(SuperFoldStatus nextState)
263 {
264     TLOGI(WmsLogTag::DMS, "TransferState from %{public}d to %{public}d", curState_.load(), nextState);
265     curState_ .store(nextState);
266 }
267 
MatchSuperFoldStatusToFoldStatus(SuperFoldStatus superFoldStatus)268 FoldStatus SuperFoldStateManager::MatchSuperFoldStatusToFoldStatus(SuperFoldStatus superFoldStatus)
269 {
270     switch (superFoldStatus) {
271         case SuperFoldStatus::EXPANDED:
272             return FoldStatus::EXPAND;
273         case SuperFoldStatus::HALF_FOLDED:
274             return FoldStatus::HALF_FOLD;
275         case SuperFoldStatus::FOLDED:
276             return FoldStatus::FOLDED;
277         case SuperFoldStatus::KEYBOARD:
278             return FoldStatus::HALF_FOLD;
279         default:
280             return FoldStatus::UNKNOWN;
281     }
282 }
283 
ReportNotifySuperFoldStatusChange(int32_t currentStatus,int32_t nextStatus,float postureAngle)284 void SuperFoldStateManager::ReportNotifySuperFoldStatusChange(int32_t currentStatus, int32_t nextStatus,
285     float postureAngle)
286 {
287     TLOGI(WmsLogTag::DMS, "currentStatus: %{public}d, nextStatus: %{public}d, postureAngle: %{public}f",
288         currentStatus, nextStatus, postureAngle);
289     int32_t ret = HiSysEventWrite(
290         OHOS::HiviewDFX::HiSysEvent::Domain::WINDOW_MANAGER,
291         "NOTIFY_FOLD_STATE_CHANGE",
292         OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR,
293         "CURRENT_FOLD_STATUS", currentStatus,
294         "NEXT_FOLD_STATUS", nextStatus,
295         "SENSOR_POSTURE", postureAngle);
296     if (ret != 0) {
297         TLOGI(WmsLogTag::DMS, "Write HiSysEvent error, ret: %{public}d", ret);
298     }
299 }
300 
HandleScreenConnectChange()301 void SuperFoldStateManager::HandleScreenConnectChange()
302 {
303     std::unique_lock<std::mutex> lock(superStatusMutex_);
304     SuperFoldStatus curFoldState = curState_.load();
305     lock.unlock();
306     if (curFoldState == SuperFoldStatus::KEYBOARD) {
307         HandleSuperFoldStatusChange(SuperFoldStatusChangeEvents::KEYBOARD_OFF);
308         HandleSuperFoldStatusChange(SuperFoldStatusChangeEvents::ANGLE_CHANGE_EXPANDED);
309     } else {
310         HandleSuperFoldStatusChange(SuperFoldStatusChangeEvents::ANGLE_CHANGE_EXPANDED);
311     }
312 }
313 
HandleSuperFoldStatusChange(SuperFoldStatusChangeEvents event)314 void SuperFoldStateManager::HandleSuperFoldStatusChange(SuperFoldStatusChangeEvents event)
315 {
316     std::unique_lock<std::mutex> lock(superStatusMutex_);
317     SuperFoldStatus curState = curState_.load();
318     SuperFoldStatus nextState = SuperFoldStatus::UNKNOWN;
319     bool isTransfer = false;
320     std::function<void (SuperFoldStatusChangeEvents)> action;
321 
322     auto item = stateManagerMap_.find({curState, event});
323     if (item != stateManagerMap_.end()) {
324         nextState = item->second.nextState;
325         action = item->second.action;
326         isTransfer = true;
327     }
328 
329     float curAngle = SuperFoldSensorManager::GetInstance().GetCurAngle();
330     TLOGD(WmsLogTag::DMS, "curAngle: %{public}f", curAngle);
331     if (isTransfer && action) {
332         HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "ssm:HandleSuperFoldStatusChange");
333         action(event);
334         TransferState(nextState);
335         lock.unlock();
336         ReportNotifySuperFoldStatusChange(static_cast<int32_t>(curState), static_cast<int32_t>(nextState), curAngle);
337         HandleDisplayNotify(event);
338         // notify
339         auto screenSession = ScreenSessionManager::GetInstance().GetDefaultScreenSession();
340         if (screenSession == nullptr) {
341             TLOGE(WmsLogTag::DMS, "screen session is null!");
342             return;
343         }
344         ScreenId screenId = screenSession->GetScreenId();
345         ScreenSessionManager::GetInstance().OnSuperFoldStatusChange(screenId, curState_.load());
346         ScreenSessionManager::GetInstance().NotifyFoldStatusChanged(
347             MatchSuperFoldStatusToFoldStatus(curState_.load()));
348     }
349 }
350 
GetCurrentStatus()351 SuperFoldStatus SuperFoldStateManager::GetCurrentStatus()
352 {
353     return curState_.load();
354 }
355 
SetCurrentStatus(SuperFoldStatus curState)356 void SuperFoldStateManager::SetCurrentStatus(SuperFoldStatus curState)
357 {
358     std::unique_lock<std::mutex> lock(superStatusMutex_);
359     curState_.store(curState);
360 }
361 
GetCurrentFoldCreaseRegion()362 sptr<FoldCreaseRegion> SuperFoldStateManager::GetCurrentFoldCreaseRegion()
363 {
364     TLOGI(WmsLogTag::DMS, "GetCurrentFoldCreaseRegion()");
365     return currentSuperFoldCreaseRegion_;
366 }
367 
GetLiveCreaseRegion()368 FoldCreaseRegion SuperFoldStateManager::GetLiveCreaseRegion()
369 {
370     TLOGI(WmsLogTag::DMS, "enter");
371     SuperFoldStatus curFoldState = ScreenSessionManager::GetInstance().GetSuperFoldStatus();
372     if (curFoldState == SuperFoldStatus::UNKNOWN || curFoldState == SuperFoldStatus::FOLDED) {
373         return FoldCreaseRegion(0, {});
374     }
375     sptr<ScreenSession> screenSession = ScreenSessionManager::GetInstance().GetScreenSession(SCREEN_ID_FULL);
376     if (screenSession == nullptr) {
377         TLOGE(WmsLogTag::DMS, "default screenSession is null");
378         return FoldCreaseRegion(0, {});
379     }
380     DisplayOrientation displayOrientation = screenSession->GetScreenProperty().GetDisplayOrientation();
381     switch (displayOrientation) {
382         case DisplayOrientation::PORTRAIT: {
383             liveCreaseRegion_ = GetFoldCreaseRegion(false, false);
384             break;
385         }
386         case DisplayOrientation::PORTRAIT_INVERTED: {
387             liveCreaseRegion_ = GetFoldCreaseRegion(false, true);
388             break;
389         }
390         case DisplayOrientation::LANDSCAPE: {
391             liveCreaseRegion_ = GetFoldCreaseRegion(true, true);
392             break;
393         }
394         case DisplayOrientation::LANDSCAPE_INVERTED: {
395             liveCreaseRegion_ = GetFoldCreaseRegion(true, false);
396             break;
397         }
398         default: {
399             TLOGE(WmsLogTag::DMS, "displayOrientation is invalid");
400         }
401     }
402     return liveCreaseRegion_;
403 }
404 
GetFoldCreaseRegionJson()405 nlohmann::ordered_json SuperFoldStateManager::GetFoldCreaseRegionJson()
406 {
407     if (superFoldCreaseRegionItems_.size() == 0) {
408         GetAllCreaseRegion();
409     }
410     nlohmann::ordered_json ret = nlohmann::ordered_json::array();
411     for (const auto& foldCreaseRegionItem : superFoldCreaseRegionItems_) {
412         nlohmann::ordered_json capabilityInfo;
413         capabilityInfo["superFoldStatus"] =
414             std::to_string(static_cast<int32_t>(foldCreaseRegionItem.superFoldStatus_));
415         capabilityInfo["displayOrientation"] =
416             std::to_string(static_cast<int32_t>(foldCreaseRegionItem.orientation_));
417         capabilityInfo["creaseRects"]["displayId"] =
418             std::to_string(static_cast<int32_t>(foldCreaseRegionItem.region_.GetDisplayId()));
419         auto creaseRects = foldCreaseRegionItem.region_.GetCreaseRects();
420         capabilityInfo["creaseRects"]["rects"] = nlohmann::ordered_json::array();
421         for (const auto& creaseRect : creaseRects) {
422             capabilityInfo["creaseRects"]["rects"].push_back({
423                 {"posX", creaseRect.posX_},
424                 {"posY", creaseRect.posY_},
425                 {"width", creaseRect.width_},
426                 {"height", creaseRect.height_}
427             });
428         }
429         ret.push_back(capabilityInfo);
430     }
431     return ret;
432 }
433 
GetAllCreaseRegion()434 void SuperFoldStateManager::GetAllCreaseRegion()
435 {
436     SuperFoldCreaseRegionItem FCreaseItem{DisplayOrientation::LANDSCAPE, SuperFoldStatus::FOLDED,
437         FoldCreaseRegion(0, {})};
438     SuperFoldCreaseRegionItem HPorCreaseItem{DisplayOrientation::PORTRAIT, SuperFoldStatus::HALF_FOLDED,
439         GetFoldCreaseRegion(false, false)};
440     SuperFoldCreaseRegionItem HLandCreaseItem{DisplayOrientation::LANDSCAPE, SuperFoldStatus::HALF_FOLDED,
441         GetFoldCreaseRegion(true, false)};
442     SuperFoldCreaseRegionItem EPorCreaseItem{DisplayOrientation::PORTRAIT, SuperFoldStatus::EXPANDED,
443         GetFoldCreaseRegion(false, false)};
444     SuperFoldCreaseRegionItem ELandCreaseItem{DisplayOrientation::LANDSCAPE, SuperFoldStatus::EXPANDED,
445         GetFoldCreaseRegion(true, true)};
446     SuperFoldCreaseRegionItem EPorInvRCreaseItem{DisplayOrientation::PORTRAIT_INVERTED, SuperFoldStatus::EXPANDED,
447         GetFoldCreaseRegion(false, true)};
448     SuperFoldCreaseRegionItem ELandInvRCreaseItem{DisplayOrientation::LANDSCAPE_INVERTED, SuperFoldStatus::EXPANDED,
449         GetFoldCreaseRegion(true, false)};
450     SuperFoldCreaseRegionItem KPorCreaseItem{DisplayOrientation::PORTRAIT, SuperFoldStatus::KEYBOARD,
451         GetFoldCreaseRegion(false, false)};
452     SuperFoldCreaseRegionItem KLandCreaseItem{DisplayOrientation::LANDSCAPE, SuperFoldStatus::KEYBOARD,
453         GetFoldCreaseRegion(true, false)};
454     superFoldCreaseRegionItems_.push_back(FCreaseItem);
455     superFoldCreaseRegionItems_.push_back(HPorCreaseItem);
456     superFoldCreaseRegionItems_.push_back(HLandCreaseItem);
457     superFoldCreaseRegionItems_.push_back(EPorCreaseItem);
458     superFoldCreaseRegionItems_.push_back(ELandCreaseItem);
459     superFoldCreaseRegionItems_.push_back(EPorInvRCreaseItem);
460     superFoldCreaseRegionItems_.push_back(ELandInvRCreaseItem);
461     superFoldCreaseRegionItems_.push_back(KPorCreaseItem);
462     superFoldCreaseRegionItems_.push_back(KLandCreaseItem);
463 }
464 
HandleDisplayNotify(SuperFoldStatusChangeEvents changeEvent)465 void SuperFoldStateManager::HandleDisplayNotify(SuperFoldStatusChangeEvents changeEvent)
466 {
467     TLOGI(WmsLogTag::DMS, "changeEvent: %{public}d", static_cast<uint32_t>(changeEvent));
468     sptr<ScreenSession> screenSession =
469         ScreenSessionManager::GetInstance().GetDefaultScreenSession();
470     if (screenSession == nullptr) {
471         TLOGE(WmsLogTag::DMS, "screen session is null");
472         return;
473     }
474     if (screenSession->GetFakeScreenSession() == nullptr) {
475         TLOGE(WmsLogTag::DMS, "fake screen session is null");
476         return;
477     }
478     switch (changeEvent) {
479         case SuperFoldStatusChangeEvents::ANGLE_CHANGE_HALF_FOLDED:
480             HandleExtendToHalfFoldDisplayNotify(screenSession);
481             TLOGI(WmsLogTag::DMS, "handle extend change to half fold");
482             break;
483         case SuperFoldStatusChangeEvents::ANGLE_CHANGE_EXPANDED:
484             HandleHalfFoldToExtendDisplayNotify(screenSession);
485             TLOGI(WmsLogTag::DMS, "handle half fold change to extend");
486             break;
487         case SuperFoldStatusChangeEvents::KEYBOARD_ON:
488             HandleKeyboardOnDisplayNotify(screenSession);
489             TLOGI(WmsLogTag::DMS, "handle keyboard on");
490             break;
491         case SuperFoldStatusChangeEvents::KEYBOARD_OFF:
492             HandleKeyboardOffDisplayNotify(screenSession);
493             TLOGI(WmsLogTag::DMS, "handle keyboard off");
494             break;
495         case SuperFoldStatusChangeEvents::SYSTEM_KEYBOARD_ON:
496             HandleSystemKeyboardStatusDisplayNotify(screenSession, true);
497             TLOGI(WmsLogTag::DMS, "handle system keyboard on");
498             break;
499         case SuperFoldStatusChangeEvents::SYSTEM_KEYBOARD_OFF:
500             HandleSystemKeyboardStatusDisplayNotify(screenSession, false);
501             TLOGI(WmsLogTag::DMS, "handle system keyboard off");
502             break;
503         default:
504             TLOGE(WmsLogTag::DMS, "nothing to handle");
505             return;
506     }
507 }
508 
HandleExtendToHalfFoldDisplayNotify(sptr<ScreenSession> screenSession)509 void SuperFoldStateManager::HandleExtendToHalfFoldDisplayNotify(sptr<ScreenSession> screenSession)
510 {
511     screenSession->UpdatePropertyByFakeInUse(true);
512     screenSession->SetIsBScreenHalf(true);
513     ScreenSessionManager::GetInstance().NotifyDisplayChanged(
514         screenSession->ConvertToDisplayInfo(), DisplayChangeEvent::SUPER_FOLD_RESOLUTION_CHANGED);
515     sptr<ScreenSession> fakeScreenSession = screenSession->GetFakeScreenSession();
516     ScreenSessionManager::GetInstance().NotifyDisplayCreate(
517         fakeScreenSession->ConvertToDisplayInfo());
518     screenSession->PropertyChange(screenSession->GetScreenProperty(),
519         ScreenPropertyChangeReason::SUPER_FOLD_STATUS_CHANGE);
520     RefreshExternalRegion();
521 }
522 
GetFoldCreaseHeight() const523 uint32_t SuperFoldStateManager::GetFoldCreaseHeight() const
524 {
525     if (currentSuperFoldCreaseRegion_ == nullptr) {
526         return DEFAULT_FOLD_REGION_HEIGHT;
527     }
528     std::vector<DMRect> creaseRects = currentSuperFoldCreaseRegion_->GetCreaseRects();
529     if (!creaseRects.empty()) {
530         return creaseRects[0].height_;
531     }
532     return DEFAULT_FOLD_REGION_HEIGHT;
533 }
534 
ForceChangeMirrorMode(sptr<ScreenSession> & mainScreenSession,sptr<ScreenSession> & secondarySession)535 DMError SuperFoldStateManager::ForceChangeMirrorMode(
536     sptr<ScreenSession>& mainScreenSession, sptr<ScreenSession>& secondarySession)
537 {
538     if (mainScreenSession == nullptr || secondarySession == nullptr) {
539         TLOGE(WmsLogTag::DMS, "screenSession is null");
540         return DMError::DM_ERROR_NULLPTR;
541     }
542     TLOGI(WmsLogTag::DMS, "currentStatus: %{public}d", GetCurrentStatus());
543     if (GetCurrentStatus() != SuperFoldStatus::EXPANDED) {
544         ScreenSessionManager::GetInstance().SetMultiScreenMode(
545             mainScreenSession->GetRSScreenId(), secondarySession->GetRSScreenId(),
546             MultiScreenMode::SCREEN_MIRROR);
547     }
548     return DMError::DM_OK;
549 }
550 
RefreshMirrorRegionInner(sptr<ScreenSession> & mainScreenSession,sptr<ScreenSession> & secondarySession)551 DMError SuperFoldStateManager::RefreshMirrorRegionInner(
552     sptr<ScreenSession>& mainScreenSession, sptr<ScreenSession>& secondarySession)
553 {
554     if (mainScreenSession == nullptr || secondarySession == nullptr) {
555         TLOGE(WmsLogTag::DMS, "mainScreenSession or secondarySession is null");
556         return DMError::DM_ERROR_NULLPTR;
557     }
558     auto mainScreenProperty = mainScreenSession->GetScreenProperty();
559     auto screenProperty = secondarySession->GetScreenProperty();
560     std::shared_ptr<RSDisplayNode> displayNode = mainScreenSession->GetDisplayNode();
561     if (displayNode == nullptr) {
562         TLOGE(WmsLogTag::DMS, "displayNode is null.");
563         return DMError::DM_ERROR_NULLPTR;
564     }
565     DMRect mirrorRegion = DMRect::NONE();
566     if (GetCurrentStatus() != SuperFoldStatus::EXPANDED) {
567         mirrorRegion.posX_ = 0;
568         mirrorRegion.posY_ = 0;
569         mirrorRegion.width_ = mainScreenProperty.GetScreenRealWidth();
570         mirrorRegion.height_ = (mainScreenProperty.GetScreenRealHeight() - GetFoldCreaseHeight()) / HEIGHT_HALF;
571         if (mirrorRegion.width_ == 0 || mirrorRegion.height_ == 0) {
572             TLOGE(WmsLogTag::DMS, "mirrorRegion.width_:%{public}d mirrorRegion.height_:%{public}d",
573                 mirrorRegion.width_, mirrorRegion.height_);
574             return DMError::DM_ERROR_INVALID_PARAM;
575         }
576     } else {
577         mirrorRegion.width_ = mainScreenProperty.GetScreenRealWidth();
578         mirrorRegion.height_ = mainScreenProperty.GetScreenRealHeight();
579     }
580     mainScreenSession->UpdateMirrorWidth(mirrorRegion.width_);
581     mainScreenSession->UpdateMirrorHeight(mirrorRegion.height_);
582     secondarySession->SetMirrorScreenRegion(secondarySession->GetScreenId(), mirrorRegion);
583     secondarySession->SetIsPhysicalMirrorSwitch(true);
584     secondarySession->EnableMirrorScreenRegion();
585     RSDisplayNodeConfig config = { secondarySession->rsId_, true, displayNode->GetId() };
586     secondarySession->ReuseDisplayNode(config);
587     return DMError::DM_OK;
588 }
589 
RefreshExternalRegion()590 DMError SuperFoldStateManager::RefreshExternalRegion()
591 {
592     if (!ScreenSessionManager::GetInstance().GetIsExtendScreenConnected()) {
593         TLOGW(WmsLogTag::DMS, "extend screen not connect");
594         return DMError::DM_OK;
595     }
596     sptr<ScreenSession> mainScreenSession = ScreenSessionManager::GetInstance().GetScreenSessionByRsId(SCREEN_ID_FULL);
597     if (mainScreenSession == nullptr) {
598         TLOGE(WmsLogTag::DMS, "GetScreenSession null");
599         return DMError::DM_ERROR_NULLPTR;
600     }
601     std::vector<ScreenId> screenIds = ScreenSessionManager::GetInstance().GetAllScreenIds();
602     for (auto screenId : screenIds) {
603         sptr<ScreenSession> secondarySession = ScreenSessionManager::GetInstance().GetScreenSession(screenId);
604         if (secondarySession == nullptr) {
605             TLOGE(WmsLogTag::DMS, "get mainScreenSession failed secondarySession null");
606             continue;
607         }
608         if (secondarySession->GetScreenProperty().GetScreenType() == ScreenType::REAL &&
609             secondarySession->GetIsExtend()) {
610             if (GetCurrentStatus() != SuperFoldStatus::EXPANDED &&
611                 secondarySession->GetScreenCombination() != ScreenCombination::SCREEN_MIRROR) {
612                 ForceChangeMirrorMode(mainScreenSession, secondarySession);
613             }
614             if (secondarySession->GetScreenCombination() == ScreenCombination::SCREEN_MIRROR) {
615                 RefreshMirrorRegionInner(mainScreenSession, secondarySession);
616             }
617         }
618     }
619     return DMError::DM_OK;
620 }
621 
HandleHalfFoldToExtendDisplayNotify(sptr<ScreenSession> screenSession)622 void SuperFoldStateManager::HandleHalfFoldToExtendDisplayNotify(sptr<ScreenSession> screenSession)
623 {
624     screenSession->UpdatePropertyByFakeInUse(false);
625     screenSession->SetIsBScreenHalf(false);
626     sptr<ScreenSession> fakeScreenSession = screenSession->GetFakeScreenSession();
627     sptr<DisplayInfo> fakeDisplayInfo = fakeScreenSession->ConvertToDisplayInfo();
628     if (fakeDisplayInfo == nullptr) {
629         TLOGE(WmsLogTag::DMS, "get fake display failed");
630         return;
631     }
632     DisplayId fakeDisplayId = fakeDisplayInfo->GetDisplayId();
633     ScreenSessionManager::GetInstance().NotifyDisplayDestroy(fakeDisplayId);
634     ScreenSessionManager::GetInstance().NotifyDisplayChanged(
635         screenSession->ConvertToDisplayInfo(),
636         DisplayChangeEvent::SUPER_FOLD_RESOLUTION_CHANGED);
637     screenSession->PropertyChange(screenSession->GetScreenProperty(),
638         ScreenPropertyChangeReason::SUPER_FOLD_STATUS_CHANGE);
639     RefreshExternalRegion();
640 }
641 
HandleKeyboardOnDisplayNotify(sptr<ScreenSession> screenSession)642 void SuperFoldStateManager::HandleKeyboardOnDisplayNotify(sptr<ScreenSession> screenSession)
643 {
644     auto screeBounds = screenSession->GetScreenProperty().GetBounds();
645     bool currFakeInUse = screenSession->GetScreenProperty().GetIsFakeInUse();
646     screenSession->UpdatePropertyByFakeInUse(false);
647     screenSession->SetIsBScreenHalf(true);
648     int32_t validheight = GetCurrentValidHeight(screenSession);
649     if (screeBounds.rect_.GetWidth() < screeBounds.rect_.GetHeight()) {
650         screenSession->SetValidHeight(validheight);
651         screenSession->SetValidWidth(screeBounds.rect_.GetWidth());
652     } else {
653         screenSession->SetValidWidth(screeBounds.rect_.GetHeight());
654         screenSession->SetValidHeight(validheight);
655     }
656     sptr<ScreenSession> fakeScreenSession = screenSession->GetFakeScreenSession();
657     sptr<DisplayInfo> fakeDisplayInfo = fakeScreenSession->ConvertToDisplayInfo();
658     if (fakeDisplayInfo == nullptr) {
659         TLOGE(WmsLogTag::DMS, "get fake display failed");
660         return;
661     }
662     DisplayId fakeDisplayId = fakeDisplayInfo->GetDisplayId();
663     if (currFakeInUse) {
664         ScreenSessionManager::GetInstance().NotifyDisplayDestroy(fakeDisplayId);
665     }
666     screenSession->PropertyChange(screenSession->GetScreenProperty(),
667         ScreenPropertyChangeReason::SUPER_FOLD_STATUS_CHANGE);
668     ScreenSessionManager::GetInstance().UpdateValidArea(
669         screenSession->GetScreenId(),
670         screenSession->GetValidWidth(),
671         screenSession->GetValidHeight());
672 }
673 
HandleKeyboardOffDisplayNotify(sptr<ScreenSession> screenSession)674 void SuperFoldStateManager::HandleKeyboardOffDisplayNotify(sptr<ScreenSession> screenSession)
675 {
676     auto screeBounds = screenSession->GetScreenProperty().GetBounds();
677     screenSession->UpdatePropertyByFakeInUse(true);
678     screenSession->SetIsBScreenHalf(true);
679     screenSession->SetValidWidth(screeBounds.rect_.GetWidth());
680     screenSession->SetValidHeight(screeBounds.rect_.GetHeight());
681     sptr<ScreenSession> fakeScreenSession = screenSession->GetFakeScreenSession();
682     ScreenSessionManager::GetInstance().NotifyDisplayCreate(
683         fakeScreenSession->ConvertToDisplayInfo());
684     screenSession->PropertyChange(screenSession->GetScreenProperty(),
685         ScreenPropertyChangeReason::SUPER_FOLD_STATUS_CHANGE);
686     ScreenSessionManager::GetInstance().UpdateValidArea(
687         screenSession->GetScreenId(),
688         screenSession->GetValidWidth(),
689         screenSession->GetValidHeight());
690 }
691 
SetSystemKeyboardStatus(bool isTpKeyboardOn)692 void SuperFoldStateManager::SetSystemKeyboardStatus(bool isTpKeyboardOn)
693 {
694     SuperFoldStatusChangeEvents events = isTpKeyboardOn ? SuperFoldStatusChangeEvents::SYSTEM_KEYBOARD_ON
695         : SuperFoldStatusChangeEvents::SYSTEM_KEYBOARD_OFF;
696     isSystemKeyboardOn_ = isTpKeyboardOn;
697     HandleDisplayNotify(events);
698 }
699 
GetSystemKeyboardStatus()700 bool SuperFoldStateManager::GetSystemKeyboardStatus()
701 {
702     return isSystemKeyboardOn_;
703 }
704 
HandleSystemKeyboardStatusDisplayNotify(sptr<ScreenSession> screenSession,bool isTpKeyboardOn)705 void SuperFoldStateManager::HandleSystemKeyboardStatusDisplayNotify(
706     sptr<ScreenSession> screenSession, bool isTpKeyboardOn)
707 {
708     SuperFoldStatus curFoldState = curState_.load();
709     TLOGD(WmsLogTag::DMS, "curFoldState: %{public}u", curFoldState);
710     if (!isKeyboardOn_ && curFoldState == SuperFoldStatus::HALF_FOLDED) {
711         screenSession->UpdatePropertyByFakeInUse(!isTpKeyboardOn);
712         screenSession->SetIsFakeInUse(!isTpKeyboardOn);
713         screenSession->SetIsBScreenHalf(true);
714     }
715     sptr<ScreenSession> fakeScreenSession = screenSession->GetFakeScreenSession();
716     sptr<DisplayInfo> fakeDisplayInfo = fakeScreenSession->ConvertToDisplayInfo();
717     if (fakeDisplayInfo == nullptr) {
718         TLOGE(WmsLogTag::DMS, "get fake display failed");
719         return;
720     }
721     if (isTpKeyboardOn) {
722         DisplayId fakeDisplayId = fakeDisplayInfo->GetDisplayId();
723         ScreenSessionManager::GetInstance().NotifyDisplayDestroy(fakeDisplayId);
724 
725         auto screeBounds = screenSession->GetScreenProperty().GetBounds();
726         int32_t validheight = GetCurrentValidHeight(screenSession);
727         if (screeBounds.rect_.GetWidth() < screeBounds.rect_.GetHeight()) {
728             screenSession->SetPointerActiveWidth(static_cast<uint32_t>(screeBounds.rect_.GetWidth()));
729             screenSession->SetPointerActiveHeight(static_cast<uint32_t>(validheight));
730         } else {
731             screenSession->SetPointerActiveWidth(static_cast<uint32_t>(screeBounds.rect_.GetHeight()));
732             screenSession->SetPointerActiveHeight(static_cast<uint32_t>(validheight));
733         }
734         TLOGD(WmsLogTag::DMS, "vh: %{public}d, paw: %{public}u, pah: %{public}u", validheight,
735             screenSession->GetPointerActiveWidth(), screenSession->GetPointerActiveHeight());
736     } else {
737         if (curFoldState == SuperFoldStatus::HALF_FOLDED) {
738             ScreenSessionManager::GetInstance().NotifyDisplayCreate(fakeDisplayInfo);
739         }
740 
741         screenSession->SetPointerActiveWidth(0);
742         screenSession->SetPointerActiveHeight(0);
743         TLOGD(WmsLogTag::DMS, "paw: %{public}u, pah: %{public}u",
744             screenSession->GetPointerActiveWidth(), screenSession->GetPointerActiveHeight());
745     }
746     screenSession->PropertyChange(screenSession->GetScreenProperty(),
747         ScreenPropertyChangeReason::SUPER_FOLD_STATUS_CHANGE);
748 }
749 
GetCurrentValidHeight(sptr<ScreenSession> screenSession)750 int32_t SuperFoldStateManager::GetCurrentValidHeight(sptr<ScreenSession> screenSession)
751 {
752     if (currentSuperFoldCreaseRegion_ != nullptr) {
753         std::vector<DMRect> creaseRects = currentSuperFoldCreaseRegion_->GetCreaseRects();
754         if (!creaseRects.empty()) {
755             TLOGI(WmsLogTag::DMS, "validheight: %{public}d", creaseRects[0].posY_);
756             return creaseRects[0].posY_;
757         }
758     }
759     TLOGE(WmsLogTag::DMS, "Get CreaseRects failed, validheight is half of height");
760     auto screeBounds = screenSession->GetScreenProperty().GetBounds();
761     if (screeBounds.rect_.GetWidth() < screeBounds.rect_.GetHeight()) {
762         return screeBounds.rect_.GetHeight() / HEIGHT_HALF;
763     } else {
764         return screeBounds.rect_.GetWidth() / HEIGHT_HALF;
765     }
766 }
767 
ChangeScreenState(bool toHalf)768 bool SuperFoldStateManager::ChangeScreenState(bool toHalf)
769 {
770     ScreenSessionManager::GetInstance().NotifyScreenMagneticStateChanged(toHalf);
771     sptr<ScreenSession> screenSession = ScreenSessionManager::GetInstance().
772         GetDefaultScreenSession();
773     if (screenSession == nullptr) {
774         TLOGE(WmsLogTag::DMS, "screen session is null!");
775         return false;
776     }
777     auto screenProperty = ScreenSessionManager::GetInstance().
778         GetPhyScreenProperty(screenSession->GetScreenId());
779     auto screenWidth = screenProperty.GetPhyBounds().rect_.GetWidth();
780     auto screenHeight = screenProperty.GetPhyBounds().rect_.GetHeight();
781     if (toHalf) {
782         screenWidth = screenProperty.GetPhyBounds().rect_.GetWidth();
783         screenHeight = screenProperty.GetPhyBounds().rect_.GetHeight() / HEIGHT_HALF;
784     }
785     OHOS::Rect rectCur{
786         .x = 0,
787         .y = 0,
788         .w = static_cast<int>(screenWidth),
789         .h = static_cast<int>(screenHeight),
790     };
791     // SCREEN_ID_FULL = 0
792     auto response = RSInterfaces::GetInstance().SetScreenActiveRect(0, rectCur);
793 #ifdef TP_FEATURE_ENABLE
794     RSInterfaces::GetInstance().SetTpFeatureConfig(TP_TYPE,
795         toHalf ? KEYBOARD_ON_CONFIG : KEYBOARD_OFF_CONFIG, TpFeatureConfigType::AFT_TP_FEATURE);
796 #endif
797     TLOGI(WmsLogTag::DMS, "rect [%{public}f , %{public}f], rs response is %{public}ld",
798         screenWidth, screenHeight, static_cast<long>(response));
799     return true;
800 }
801 
GetKeyboardState()802 bool SuperFoldStateManager::GetKeyboardState()
803 {
804     TLOGI(WmsLogTag::DMS, "GetKeyboardState isKeyboardOn_ : %{public}d", isKeyboardOn_);
805     return isKeyboardOn_;
806 }
807 } // Rosen
808 } // OHOS