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 ¶m : 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