• 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 #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