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 #include "fold_screen_controller/secondary_display_fold_policy.h"
16 #include <hisysevent.h>
17 #include <hitrace_meter.h>
18 #include <transaction/rs_interfaces.h>
19 #include "session/screen/include/screen_session.h"
20 #include "screen_session_manager.h"
21 #include "screen_scene_config.h"
22
23 #include "window_manager_hilog.h"
24
25 #ifdef POWER_MANAGER_ENABLE
26 #include <power_mgr_client.h>
27 #endif
28
29 namespace OHOS::Rosen {
30 namespace {
31 const ScreenId SCREEN_ID_FULL = 0;
32 const int32_t MAIN_STATUS_WIDTH = 0;
33 const int32_t FULL_STATUS_WIDTH = 1;
34 const int32_t GLOBAL_FULL_STATUS_WIDTH = 2;
35 const int32_t SCREEN_HEIGHT = 3;
36 const int32_t FULL_STATUS_OFFSET_X = 4;
37 constexpr uint32_t HALF_DIVIDER = 2;
38 #ifdef TP_FEATURE_ENABLE
39 const int32_t TP_TYPE = 12;
40 const char* STATUS_MAIN = "version:3+main";
41 const char* STATUS_GLOBAL_FULL = "version:3+whole";
42 const char* STATUS_FULL = "version:3+minor";
43 #endif
44 } // namespace
45
SecondaryDisplayFoldPolicy(std::recursive_mutex & displayInfoMutex,std::shared_ptr<TaskScheduler> screenPowerTaskScheduler)46 SecondaryDisplayFoldPolicy::SecondaryDisplayFoldPolicy(std::recursive_mutex& displayInfoMutex,
47 std::shared_ptr<TaskScheduler> screenPowerTaskScheduler)
48 : displayInfoMutex_(displayInfoMutex), screenPowerTaskScheduler_(screenPowerTaskScheduler)
49 {
50 InitScreenParams();
51 std::vector<int32_t> screenParamsSigned;
52 for (uint32_t ele : screenParams_) {
53 screenParamsSigned.emplace_back(static_cast<int32_t>(ele));
54 }
55 ScreenId screenIdFull = 0;
56 int32_t foldCreaseRegionABPosX = 0;
57 int32_t foldCreaseRegionABPosY = screenParamsSigned[MAIN_STATUS_WIDTH]; // 1008
58 int32_t foldCreaseRegionABPosHeight = screenParamsSigned[GLOBAL_FULL_STATUS_WIDTH] -
59 screenParamsSigned[FULL_STATUS_WIDTH] - screenParamsSigned[MAIN_STATUS_WIDTH]; // 128
60 int32_t foldCreaseRegionABPosWidth = screenParamsSigned[SCREEN_HEIGHT]; // 2232
61 int32_t foldCreaseRegionBCPosX = 0;
62 // 2224
63 int32_t foldCreaseRegionBCPosY =
64 screenParamsSigned[GLOBAL_FULL_STATUS_WIDTH] -
65 ((screenParamsSigned[FULL_STATUS_WIDTH] / HALF_DIVIDER) - (foldCreaseRegionABPosHeight / HALF_DIVIDER));
66 int32_t foldCreaseRegionBCPosWidth = screenParamsSigned[SCREEN_HEIGHT]; // 2232
67 int32_t foldCreaseRegionBCPosHeight = foldCreaseRegionABPosHeight; // 128
68 TLOGW(WmsLogTag::DMS, "created, screenIdFull = %{public}" PRIu64", foldCreaseRegionABPosX = %{public}d,\
69 foldCreaseRegionABPosY = %{public}d, foldCreaseRegionABPosHeight = %{public}d,\
70 foldCreaseRegionABPosWidth = %{public}d, foldCreaseRegionBCPosX = %{public}d,\
71 foldCreaseRegionBCPosY = %{public}d, foldCreaseRegionBCPosWidth = %{public}d,\
72 foldCreaseRegionBCPosHeight = %{public}d", screenIdFull, foldCreaseRegionABPosX, foldCreaseRegionABPosY,
73 foldCreaseRegionABPosHeight, foldCreaseRegionABPosWidth, foldCreaseRegionBCPosX, foldCreaseRegionBCPosY,
74 foldCreaseRegionBCPosWidth, foldCreaseRegionBCPosHeight);
75 std::vector<DMRect> rect = {
76 {
77 foldCreaseRegionABPosX, foldCreaseRegionABPosY,
78 static_cast<uint32_t>(foldCreaseRegionABPosWidth), static_cast<uint32_t>(foldCreaseRegionABPosHeight)
79 },
80 {
81 foldCreaseRegionBCPosX, foldCreaseRegionBCPosY,
82 static_cast<uint32_t>(foldCreaseRegionBCPosWidth), static_cast<uint32_t>(foldCreaseRegionBCPosHeight)
83 }
84 };
85 currentFoldCreaseRegion_ = new FoldCreaseRegion(screenIdFull, rect);
86 }
87
ChangeScreenDisplayMode(FoldDisplayMode displayMode,DisplayModeChangeReason reason)88 void SecondaryDisplayFoldPolicy::ChangeScreenDisplayMode(FoldDisplayMode displayMode, DisplayModeChangeReason reason)
89 {
90 SetLastCacheDisplayMode(displayMode);
91 if (GetModeChangeRunningStatus()) {
92 TLOGW(WmsLogTag::DMS, "last process not complete, skip mode: %{public}d", displayMode);
93 return;
94 }
95 sptr<ScreenSession> screenSession = ScreenSessionManager::GetInstance().GetScreenSession(SCREEN_ID_FULL);
96 if (screenSession == nullptr) {
97 TLOGE(WmsLogTag::DMS, "default screenSession is null");
98 return;
99 }
100 if (displayMode == FoldDisplayMode::UNKNOWN) {
101 TLOGW(WmsLogTag::DMS, "displayMode is unknown");
102 } else {
103 ChangeSuperScreenDisplayMode(screenSession, displayMode);
104 }
105 ReportFoldDisplayModeChange(displayMode);
106 {
107 std::lock_guard<std::recursive_mutex> lock_mode(displayModeMutex_);
108 currentDisplayMode_ = displayMode;
109 lastDisplayMode_ = displayMode;
110 }
111 ScreenSessionManager::GetInstance().NotifyDisplayModeChanged(displayMode);
112 }
113
SendSensorResult(FoldStatus foldStatus)114 void SecondaryDisplayFoldPolicy::SendSensorResult(FoldStatus foldStatus)
115 {
116 TLOGW(WmsLogTag::DMS, "FoldStatus: %{public}d", foldStatus);
117 FoldDisplayMode displayMode = GetModeMatchStatus();
118 ChangeScreenDisplayMode(displayMode);
119 }
120
SetOnBootAnimation(bool onBootAnimation)121 void SecondaryDisplayFoldPolicy::SetOnBootAnimation(bool onBootAnimation)
122 {
123 TLOGW(WmsLogTag::DMS, "onBootAnimation: %{public}d", onBootAnimation);
124 onBootAnimation_ = onBootAnimation;
125 if (!onBootAnimation_) {
126 TLOGW(WmsLogTag::DMS, "when boot animation finished, change display mode");
127 RecoverWhenBootAnimationExit();
128 }
129 }
130
RecoverWhenBootAnimationExit()131 void SecondaryDisplayFoldPolicy::RecoverWhenBootAnimationExit()
132 {
133 TLOGW(WmsLogTag::DMS, "CurrentScreen(%{public}" PRIu64 ")", screenId_);
134 FoldDisplayMode displayMode = GetModeMatchStatus();
135 ChangeScreenDisplayMode(displayMode);
136 }
137
GetModeMatchStatus()138 FoldDisplayMode SecondaryDisplayFoldPolicy::GetModeMatchStatus()
139 {
140 FoldDisplayMode displayMode = FoldDisplayMode::MAIN;
141 switch (currentFoldStatus_) {
142 case FoldStatus::EXPAND: {
143 displayMode = FoldDisplayMode::FULL;
144 break;
145 }
146 case FoldStatus::FOLDED: {
147 displayMode = FoldDisplayMode::MAIN;
148 break;
149 }
150 case FoldStatus::HALF_FOLD: {
151 displayMode = FoldDisplayMode::FULL;
152 break;
153 }
154 case FoldStatus::FOLD_STATE_EXPAND_WITH_SECOND_EXPAND: {
155 displayMode = FoldDisplayMode::GLOBAL_FULL;
156 break;
157 }
158 case FoldStatus::FOLD_STATE_EXPAND_WITH_SECOND_HALF_FOLDED: {
159 displayMode = FoldDisplayMode::GLOBAL_FULL;
160 break;
161 }
162 case FoldStatus::FOLD_STATE_FOLDED_WITH_SECOND_EXPAND: {
163 displayMode = FoldDisplayMode::MAIN;
164 break;
165 }
166 case FoldStatus::FOLD_STATE_FOLDED_WITH_SECOND_HALF_FOLDED: {
167 displayMode = FoldDisplayMode::MAIN;
168 break;
169 }
170 case FoldStatus::FOLD_STATE_HALF_FOLDED_WITH_SECOND_EXPAND: {
171 displayMode = FoldDisplayMode::GLOBAL_FULL;
172 break;
173 }
174 case FoldStatus::FOLD_STATE_HALF_FOLDED_WITH_SECOND_HALF_FOLDED: {
175 displayMode = FoldDisplayMode::GLOBAL_FULL;
176 break;
177 }
178 default: {
179 TLOGW(WmsLogTag::DMS, "FoldStatus is invalid");
180 }
181 }
182 TLOGW(WmsLogTag::DMS, "displayMode: %{public}d", displayMode);
183 return displayMode;
184 }
185
ChangeSuperScreenDisplayMode(sptr<ScreenSession> screenSession,FoldDisplayMode displayMode)186 void SecondaryDisplayFoldPolicy::ChangeSuperScreenDisplayMode(sptr<ScreenSession> screenSession,
187 FoldDisplayMode displayMode)
188 {
189 HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "ssm:ChangeScreenDisplayMode(displayMode = %" PRIu64")", displayMode);
190 {
191 std::lock_guard<std::recursive_mutex> lock_mode(displayModeMutex_);
192 if (currentDisplayMode_ == displayMode) {
193 TLOGW(WmsLogTag::DMS, "already in displayMode %{public}d", displayMode);
194 return;
195 }
196 }
197 SetSecondaryDisplayModeChangeStatus(true);
198 SendPropertyChangeResult(screenSession, SCREEN_ID_FULL, ScreenPropertyChangeReason::FOLD_SCREEN_EXPAND,
199 displayMode);
200 if (currentDisplayMode_ != displayMode) {
201 if ((currentDisplayMode_ == FoldDisplayMode::GLOBAL_FULL && displayMode == FoldDisplayMode::FULL) ||
202 (currentDisplayMode_ == FoldDisplayMode::FULL && displayMode == FoldDisplayMode::MAIN) ||
203 (currentDisplayMode_ == FoldDisplayMode::GLOBAL_FULL && displayMode == FoldDisplayMode::MAIN)) {
204 return;
205 }
206 }
207 auto taskScreenOnFullOn = [=] {
208 screenId_ = SCREEN_ID_FULL;
209 PowerMgr::PowerMgrClient::GetInstance().WakeupDeviceAsync();
210 SetdisplayModeChangeStatus(false);
211 };
212 screenPowerTaskScheduler_->PostAsyncTask(taskScreenOnFullOn, "screenOnFullOnTask");
213 }
214
SendPropertyChangeResult(sptr<ScreenSession> screenSession,ScreenId screenId,ScreenPropertyChangeReason reason,FoldDisplayMode displayMode)215 void SecondaryDisplayFoldPolicy::SendPropertyChangeResult(sptr<ScreenSession> screenSession, ScreenId screenId,
216 ScreenPropertyChangeReason reason, FoldDisplayMode displayMode)
217 {
218 std::lock_guard<std::recursive_mutex> lock_info(displayInfoMutex_);
219 screenProperty_ = ScreenSessionManager::GetInstance().GetPhyScreenProperty(screenId);
220 if (displayMode == FoldDisplayMode::FULL) {
221 SetStatusFullActiveRectAndTpFeature(screenProperty_);
222 } else if (displayMode == FoldDisplayMode::MAIN) {
223 reason = ScreenPropertyChangeReason::FOLD_SCREEN_FOLDING;
224 SetStatusMainActiveRectAndTpFeature(screenProperty_);
225 } else if (displayMode == FoldDisplayMode::GLOBAL_FULL) {
226 SetStatusGlobalFullActiveRectAndTpFeature(screenProperty_);
227 } else {
228 TLOGW(WmsLogTag::DMS, "unKnown displayMode");
229 }
230 screenSession->UpdatePropertyByFoldControl(screenProperty_, displayMode);
231 screenSession->PropertyChange(screenSession->GetScreenProperty(), reason);
232 if (displayMode == FoldDisplayMode::MAIN) {
233 screenSession->SetRotationAndScreenRotationOnly(Rotation::ROTATION_0);
234 }
235 TLOGI(WmsLogTag::DMS, "screenBounds : width_= %{public}f, height_= %{public}f",
236 screenSession->GetScreenProperty().GetBounds().rect_.width_,
237 screenSession->GetScreenProperty().GetBounds().rect_.height_);
238 }
239
SetStatusFullActiveRectAndTpFeature(ScreenProperty & screenProperty)240 void SecondaryDisplayFoldPolicy::SetStatusFullActiveRectAndTpFeature(ScreenProperty &screenProperty)
241 {
242 auto fullStatusScreenBounds = RRect({0, screenParams_[FULL_STATUS_OFFSET_X],
243 screenParams_[FULL_STATUS_WIDTH], screenParams_[SCREEN_HEIGHT]}, 0.0f, 0.0f);
244 screenProperty.SetBounds(fullStatusScreenBounds);
245 OHOS::Rect rectCur{
246 .x = 0,
247 .y = screenParams_[FULL_STATUS_OFFSET_X],
248 .w = screenParams_[SCREEN_HEIGHT],
249 .h = screenParams_[FULL_STATUS_WIDTH],
250 };
251 if (!onBootAnimation_) {
252 RSInterfaces::GetInstance().SetScreenActiveRect(0, rectCur);
253 }
254 #ifdef TP_FEATURE_ENABLE
255 RSInterfaces::GetInstance().SetTpFeatureConfig(TP_TYPE, STATUS_FULL, TpFeatureConfigType::AFT_TP_FEATURE);
256 #endif
257 SetSecondaryDisplayModeChangeStatus(false);
258 }
259
SetStatusMainActiveRectAndTpFeature(ScreenProperty & screenProperty)260 void SecondaryDisplayFoldPolicy::SetStatusMainActiveRectAndTpFeature(ScreenProperty &screenProperty)
261 {
262 auto mianStatusScreenBounds =
263 RRect({0, 0, screenParams_[MAIN_STATUS_WIDTH], screenParams_[SCREEN_HEIGHT]}, 0.0f, 0.0f);
264 screenProperty.SetBounds(mianStatusScreenBounds);
265 OHOS::Rect rectCur{
266 .x = 0,
267 .y = 0,
268 .w = screenParams_[SCREEN_HEIGHT],
269 .h = screenParams_[MAIN_STATUS_WIDTH],
270 };
271 if (!onBootAnimation_) {
272 RSInterfaces::GetInstance().SetScreenActiveRect(0, rectCur);
273 }
274 #ifdef TP_FEATURE_ENABLE
275 RSInterfaces::GetInstance().SetTpFeatureConfig(TP_TYPE, STATUS_MAIN, TpFeatureConfigType::AFT_TP_FEATURE);
276 #endif
277 SetSecondaryDisplayModeChangeStatus(false);
278 }
279
SetStatusGlobalFullActiveRectAndTpFeature(ScreenProperty & screenProperty)280 void SecondaryDisplayFoldPolicy::SetStatusGlobalFullActiveRectAndTpFeature(ScreenProperty &screenProperty)
281 {
282 auto globalFullStatusScreenBounds =
283 RRect({0, 0, screenParams_[GLOBAL_FULL_STATUS_WIDTH], screenParams_[SCREEN_HEIGHT]}, 0.0f, 0.0f);
284 screenProperty.SetBounds(globalFullStatusScreenBounds);
285 OHOS::Rect rectCur{
286 .x = 0,
287 .y = 0,
288 .w = screenParams_[SCREEN_HEIGHT],
289 .h = screenParams_[GLOBAL_FULL_STATUS_WIDTH],
290 };
291 if (!onBootAnimation_) {
292 RSInterfaces::GetInstance().SetScreenActiveRect(0, rectCur);
293 }
294 #ifdef TP_FEATURE_ENABLE
295 RSInterfaces::GetInstance().SetTpFeatureConfig(TP_TYPE, STATUS_GLOBAL_FULL, TpFeatureConfigType::AFT_TP_FEATURE);
296 #endif
297 SetSecondaryDisplayModeChangeStatus(false);
298 }
299
ReportFoldDisplayModeChange(FoldDisplayMode displayMode)300 void SecondaryDisplayFoldPolicy::ReportFoldDisplayModeChange(FoldDisplayMode displayMode)
301 {
302 int32_t mode = static_cast<int32_t>(displayMode);
303 TLOGW(WmsLogTag::DMS, "displayMode: %{public}d", mode);
304 int32_t ret = HiSysEventWrite(
305 OHOS::HiviewDFX::HiSysEvent::Domain::WINDOW_MANAGER,
306 "DISPLAY_MODE",
307 OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR,
308 "FOLD_DISPLAY_MODE", mode);
309 if (ret != 0) {
310 TLOGE(WmsLogTag::DMS, "write HiSysEvent error, ret: %{public}d", ret);
311 }
312 }
313
GetCurrentFoldCreaseRegion()314 sptr<FoldCreaseRegion> SecondaryDisplayFoldPolicy::GetCurrentFoldCreaseRegion()
315 {
316 return currentFoldCreaseRegion_;
317 }
318
InitScreenParams()319 void SecondaryDisplayFoldPolicy::InitScreenParams()
320 {
321 std::vector<DisplayPhysicalResolution> resolutions = ScreenSceneConfig::GetAllDisplayPhysicalConfig();
322 for (auto &resolution : resolutions) {
323 if (FoldDisplayMode::MAIN == resolution.foldDisplayMode_) {
324 screenParams_.push_back(resolution.physicalWidth_);
325 } else if (FoldDisplayMode::FULL == resolution.foldDisplayMode_) {
326 screenParams_.push_back(resolution.physicalWidth_);
327 } else if (FoldDisplayMode::GLOBAL_FULL == resolution.foldDisplayMode_) {
328 screenParams_.push_back(resolution.physicalWidth_);
329 screenParams_.push_back(resolution.physicalHeight_);
330 } else {
331 TLOGW(WmsLogTag::DMS, "unKnown displayMode");
332 }
333 }
334 screenParams_.push_back(screenParams_[GLOBAL_FULL_STATUS_WIDTH] - screenParams_[FULL_STATUS_WIDTH]);
335 TLOGI(WmsLogTag::DMS,
336 "PhysicalResolution : mainStatusWidth_= %{public}d, fullStatusWidth_= %{public}d, gloablFullStatusWidth_="
337 "%{public}d, screenHeight_= %{public}d, fullStatusOffsetX_= %{public}d",
338 screenParams_[MAIN_STATUS_WIDTH], screenParams_[FULL_STATUS_WIDTH],
339 screenParams_[GLOBAL_FULL_STATUS_WIDTH], screenParams_[SCREEN_HEIGHT],
340 screenParams_[FULL_STATUS_OFFSET_X]);
341 }
342
GetScreenParams()343 std::vector<uint32_t> SecondaryDisplayFoldPolicy::GetScreenParams()
344 {
345 return screenParams_;
346 }
347
SetScreenSnapshotRect(RSSurfaceCaptureConfig & config)348 void SecondaryDisplayFoldPolicy::SetScreenSnapshotRect(RSSurfaceCaptureConfig& config)
349 {
350 if (currentDisplayMode_ == FoldDisplayMode::MAIN) {
351 config.screenLeft = 0;
352 config.screenTop = 0;
353 config.screenWidth = static_cast<float>(screenParams_[SCREEN_HEIGHT]);
354 config.screenHeight = static_cast<float>(screenParams_[MAIN_STATUS_WIDTH]);
355 } else if (currentDisplayMode_ == FoldDisplayMode::FULL) {
356 config.screenLeft = 0;
357 config.screenTop = static_cast<float>(screenParams_[FULL_STATUS_OFFSET_X]);
358 config.screenWidth = static_cast<float>(screenParams_[SCREEN_HEIGHT]);
359 config.screenHeight = static_cast<float>(screenParams_[FULL_STATUS_WIDTH]);
360 } else if (currentDisplayMode_ == FoldDisplayMode::GLOBAL_FULL) {
361 config.screenLeft = 0;
362 config.screenTop = 0;
363 config.screenWidth = static_cast<float>(screenParams_[SCREEN_HEIGHT]);
364 config.screenHeight = static_cast<float>(screenParams_[GLOBAL_FULL_STATUS_WIDTH]);
365 }
366 }
367
SetMainScreenRegion(DMRect & mainScreenRegion)368 void SecondaryDisplayFoldPolicy::SetMainScreenRegion(DMRect& mainScreenRegion)
369 {
370 if (currentDisplayMode_ == FoldDisplayMode::MAIN) {
371 mainScreenRegion.posX_ = 0;
372 mainScreenRegion.posY_ = 0;
373 mainScreenRegion.width_ = screenParams_[SCREEN_HEIGHT];
374 mainScreenRegion.height_ = screenParams_[MAIN_STATUS_WIDTH];
375 } else if (currentDisplayMode_ == FoldDisplayMode::FULL) {
376 mainScreenRegion.posX_ = 0;
377 mainScreenRegion.posY_ = static_cast<int32_t>(screenParams_[FULL_STATUS_OFFSET_X]);
378 mainScreenRegion.width_ = screenParams_[SCREEN_HEIGHT];
379 mainScreenRegion.height_ = screenParams_[FULL_STATUS_WIDTH];
380 } else if (currentDisplayMode_ == FoldDisplayMode::GLOBAL_FULL) {
381 mainScreenRegion.posX_ = 0;
382 mainScreenRegion.posY_ = 0;
383 mainScreenRegion.width_ = screenParams_[SCREEN_HEIGHT];
384 mainScreenRegion.height_ = screenParams_[GLOBAL_FULL_STATUS_WIDTH];
385 }
386 }
387
SetSecondaryDisplayModeChangeStatus(bool status)388 void SecondaryDisplayFoldPolicy::SetSecondaryDisplayModeChangeStatus(bool status)
389 {
390 if (status) {
391 secondaryPengdingTask_ = SECONDARY_FOLD_TO_EXPAND_TASK_NUM;
392 startTimePoint_ = std::chrono::steady_clock::now();
393 displayModeChangeRunning_ = status;
394 } else {
395 secondaryPengdingTask_ --;
396 if (secondaryPengdingTask_ > 0) {
397 return;
398 }
399 displayModeChangeRunning_ = false;
400 endTimePoint_ = std::chrono::steady_clock::now();
401 if (lastCachedisplayMode_.load() != GetScreenDisplayMode()) {
402 ScreenSessionManager::GetInstance().TriggerDisplayModeUpdate(lastCachedisplayMode_.load());
403 }
404 }
405 }
406
407 } // namespace OHOS::Rosen