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