• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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 "abstract_display_controller.h"
17 
18 #include <cinttypes>
19 #include <hitrace_meter.h>
20 #include <sstream>
21 #include <surface.h>
22 
23 #include "display_cutout_controller.h"
24 #include "display_manager_agent_controller.h"
25 #include "display_manager_service.h"
26 #include "screen_group.h"
27 #include "screen_rotation_controller.h"
28 #include "surface_capture_future.h"
29 #include "window_manager_hilog.h"
30 #include "sys_cap_util.h"
31 
32 namespace OHOS::Rosen {
AbstractDisplayController(std::recursive_mutex & mutex,DisplayStateChangeListener listener)33 AbstractDisplayController::AbstractDisplayController(std::recursive_mutex& mutex, DisplayStateChangeListener listener)
34     : mutex_(mutex), rsInterface_(RSInterfaces::GetInstance()), displayStateChangeListener_(listener)
35 {
36 }
37 
~AbstractDisplayController()38 AbstractDisplayController::~AbstractDisplayController()
39 {
40     abstractScreenController_ = nullptr;
41 }
42 
Init(sptr<AbstractScreenController> abstractScreenController)43 void AbstractDisplayController::Init(sptr<AbstractScreenController> abstractScreenController)
44 {
45     TLOGD(WmsLogTag::DMS, "display controller init");
46     displayCount_ = 0;
47     abstractScreenController_ = abstractScreenController;
48     abstractScreenCallback_ = new(std::nothrow) AbstractScreenController::AbstractScreenCallback();
49     if (abstractScreenCallback_ == nullptr) {
50         TLOGE(WmsLogTag::DMS, "abstractScreenCallback init failed");
51         return;
52     }
53     abstractScreenCallback_->onConnect_
54         = std::bind(&AbstractDisplayController::OnAbstractScreenConnect, this, std::placeholders::_1);
55     abstractScreenCallback_->onDisconnect_
56         = std::bind(&AbstractDisplayController::OnAbstractScreenDisconnect, this, std::placeholders::_1);
57     abstractScreenCallback_->onChange_
58         = std::bind(&AbstractDisplayController::OnAbstractScreenChange, this, std::placeholders::_1,
59         std::placeholders::_2);
60     abstractScreenController->RegisterAbstractScreenCallback(abstractScreenCallback_);
61 }
62 
GetDefaultScreenId()63 ScreenId AbstractDisplayController::GetDefaultScreenId()
64 {
65     return rsInterface_.GetDefaultScreenId();
66 }
67 
GetScreenActiveMode(ScreenId id)68 RSScreenModeInfo AbstractDisplayController::GetScreenActiveMode(ScreenId id)
69 {
70     return rsInterface_.GetScreenActiveMode(id);
71 }
72 
GetAbstractDisplay(DisplayId displayId) const73 sptr<AbstractDisplay> AbstractDisplayController::GetAbstractDisplay(DisplayId displayId) const
74 {
75     if (displayId == DISPLAY_ID_INVALID) {
76         TLOGE(WmsLogTag::DMS, "display id is invalid.");
77         return nullptr;
78     }
79     std::lock_guard<std::recursive_mutex> lock(mutex_);
80     auto iter = abstractDisplayMap_.find(displayId);
81     if (iter == abstractDisplayMap_.end()) {
82         TLOGE(WmsLogTag::DMS, "Failed to get AbstractDisplay %{public}" PRIu64", return nullptr!", displayId);
83         return nullptr;
84     }
85     return iter->second;
86 }
87 
GetAbstractDisplayByScreen(ScreenId screenId) const88 sptr<AbstractDisplay> AbstractDisplayController::GetAbstractDisplayByScreen(ScreenId screenId) const
89 {
90     if (screenId == SCREEN_ID_INVALID) {
91         TLOGE(WmsLogTag::DMS, "screen id is invalid.");
92         return nullptr;
93     }
94     std::lock_guard<std::recursive_mutex> lock(mutex_);
95     for (auto iter : abstractDisplayMap_) {
96         sptr<AbstractDisplay> display = iter.second;
97         if (display->GetAbstractScreenId() == screenId) {
98             return display;
99         }
100     }
101     TLOGE(WmsLogTag::DMS, "fail to get AbstractDisplay %{public}" PRIu64"", screenId);
102     return nullptr;
103 }
104 
GetAllDisplayIds() const105 std::vector<DisplayId> AbstractDisplayController::GetAllDisplayIds() const
106 {
107     std::lock_guard<std::recursive_mutex> lock(mutex_);
108     std::vector<DisplayId> res;
109     for (auto iter = abstractDisplayMap_.begin(); iter != abstractDisplayMap_.end(); ++iter) {
110         res.push_back(iter->first);
111     }
112     return res;
113 }
114 
GetScreenSnapshot(DisplayId displayId)115 std::shared_ptr<Media::PixelMap> AbstractDisplayController::GetScreenSnapshot(DisplayId displayId)
116 {
117     sptr<AbstractDisplay> abstractDisplay = GetAbstractDisplay(displayId);
118     if (abstractDisplay == nullptr) {
119         TLOGE(WmsLogTag::DMS, "GetAbstractDisplay failed");
120         return nullptr;
121     }
122     ScreenId dmsScreenId = abstractDisplay->GetAbstractScreenId();
123     std::shared_ptr<RSDisplayNode> displayNode = abstractScreenController_->GetRSDisplayNodeByScreenId(dmsScreenId);
124 
125     std::lock_guard<std::recursive_mutex> lock(mutex_);
126     std::shared_ptr<SurfaceCaptureFuture> callback = std::make_shared<SurfaceCaptureFuture>();
127     rsInterface_.TakeSurfaceCapture(displayNode, callback);
128     std::shared_ptr<Media::PixelMap> screenshot = callback->GetResult(2000); // wait for <= 2000ms
129     if (screenshot == nullptr) {
130         TLOGE(WmsLogTag::DMS, "Failed to get pixelmap from RS, return nullptr!");
131     }
132 
133     // notify dm listener
134     sptr<ScreenshotInfo> snapshotInfo = new ScreenshotInfo();
135     snapshotInfo->SetTrigger(SysCapUtil::GetClientName());
136     snapshotInfo->SetDisplayId(displayId);
137     DisplayManagerAgentController::GetInstance().OnScreenshot(snapshotInfo);
138 
139     return screenshot;
140 }
141 
OnAbstractScreenConnect(sptr<AbstractScreen> absScreen)142 void AbstractDisplayController::OnAbstractScreenConnect(sptr<AbstractScreen> absScreen)
143 {
144     if (absScreen == nullptr) {
145         TLOGE(WmsLogTag::DMS, "absScreen is null");
146         return;
147     }
148     TLOGI(WmsLogTag::DMS, "connect new screen. id:%{public}" PRIu64"", absScreen->dmsId_);
149     std::lock_guard<std::recursive_mutex> lock(mutex_);
150     sptr<AbstractScreenGroup> group = absScreen->GetGroup();
151     if (group == nullptr) {
152         TLOGE(WmsLogTag::DMS, "the group information of the screen is wrong");
153         return;
154     }
155     if (group->combination_ == ScreenCombination::SCREEN_ALONE || group->GetChildCount() == 1) {
156         BindAloneScreenLocked(absScreen);
157     } else if (group->combination_ == ScreenCombination::SCREEN_MIRROR) {
158         TLOGI(WmsLogTag::DMS, "ScreenCombination::SCREEN_MIRROR, AddScreenToMirrorLocked");
159         AddScreenToMirrorLocked(absScreen);
160     } else if (group->combination_ == ScreenCombination::SCREEN_EXPAND) {
161         TLOGI(WmsLogTag::DMS, "ScreenCombination::SCREEN_EXPAND, AddScreenToExpandLocked");
162         AddScreenToExpandLocked(absScreen);
163     } else {
164         TLOGE(WmsLogTag::DMS, "support in future. combination:%{public}u", group->combination_);
165     }
166 }
167 
OnAbstractScreenDisconnect(sptr<AbstractScreen> absScreen)168 void AbstractDisplayController::OnAbstractScreenDisconnect(sptr<AbstractScreen> absScreen)
169 {
170     if (absScreen == nullptr) {
171         TLOGE(WmsLogTag::DMS, "the information of the screen is wrong");
172         return;
173     }
174     sptr<AbstractScreenGroup> screenGroup = absScreen->GetGroup();
175     if (screenGroup == nullptr) {
176         TLOGE(WmsLogTag::DMS, "the group information of the screen is wrong");
177         return;
178     }
179 
180     TLOGI(WmsLogTag::DMS, "disconnect screen. id:%{public}" PRIu64"", absScreen->dmsId_);
181     DisplayId absDisplayId = DISPLAY_ID_INVALID;
182     sptr<AbstractDisplay> abstractDisplay = nullptr;
183     if (screenGroup->combination_ == ScreenCombination::SCREEN_ALONE
184         || screenGroup->combination_ == ScreenCombination::SCREEN_MIRROR) {
185         absDisplayId = ProcessNormalScreenDisconnected(absScreen, screenGroup, abstractDisplay);
186     } else if (screenGroup->combination_ == ScreenCombination::SCREEN_EXPAND) {
187         absDisplayId = ProcessExpandScreenDisconnected(absScreen, screenGroup, abstractDisplay);
188     } else {
189         TLOGE(WmsLogTag::DMS, "support in future. combination:%{public}u", screenGroup->combination_);
190     }
191     if (absDisplayId == DISPLAY_ID_INVALID) {
192         TLOGE(WmsLogTag::DMS, "the displayId of the disconnected expand screen was not found");
193         return;
194     }
195 
196     if (screenGroup->combination_ == ScreenCombination::SCREEN_ALONE
197         || screenGroup->combination_ == ScreenCombination::SCREEN_MIRROR) {
198         if (screenGroup->GetChildCount() == 0) {
199             std::lock_guard<std::recursive_mutex> lock(mutex_);
200             DisplayManagerAgentController::GetInstance().OnDisplayDestroy(absDisplayId);
201             abstractDisplayMap_.erase(absDisplayId);
202         }
203     } else if (screenGroup->combination_ == ScreenCombination::SCREEN_EXPAND) {
204         SetDisplayStateChangeListener(abstractDisplay, DisplayStateChangeType::DESTROY);
205         std::lock_guard<std::recursive_mutex> lock(mutex_);
206         DisplayManagerAgentController::GetInstance().OnDisplayDestroy(absDisplayId);
207         abstractDisplayMap_.erase(absDisplayId);
208     } else {
209         TLOGE(WmsLogTag::DMS, "support in future. combination:%{public}u", screenGroup->combination_);
210     }
211 }
212 
ProcessNormalScreenDisconnected(sptr<AbstractScreen> absScreen,sptr<AbstractScreenGroup> screenGroup,sptr<AbstractDisplay> & absDisplay)213 DisplayId AbstractDisplayController::ProcessNormalScreenDisconnected(
214     sptr<AbstractScreen> absScreen, sptr<AbstractScreenGroup> screenGroup, sptr<AbstractDisplay>& absDisplay)
215 {
216     TLOGI(WmsLogTag::DMS, "normal screen disconnect");
217     if (absScreen == nullptr || screenGroup == nullptr) {
218         TLOGE(WmsLogTag::DMS, "Invalid params as nullptr.");
219         return DISPLAY_ID_INVALID;
220     }
221     ScreenId defaultScreenId = abstractScreenController_->GetDefaultAbstractScreenId();
222     sptr<AbstractScreen> defaultScreen = abstractScreenController_->GetAbstractScreen(defaultScreenId);
223     for (auto iter = abstractDisplayMap_.begin(); iter != abstractDisplayMap_.end(); iter++) {
224         DisplayId displayId = iter->first;
225         sptr<AbstractDisplay> abstractDisplay = iter->second;
226         if (abstractDisplay->GetAbstractScreenId() == absScreen->dmsId_) {
227             TLOGI(WmsLogTag::DMS, "normal screen disconnect, displayId: %{public}" PRIu64", screenId:"
228                 " %{public}" PRIu64"", displayId, abstractDisplay->GetAbstractScreenId());
229             abstractDisplay->BindAbstractScreen(defaultScreen);
230             absDisplay = abstractDisplay;
231             return displayId;
232         }
233     }
234     return DISPLAY_ID_INVALID;
235 }
236 
ProcessExpandScreenDisconnected(sptr<AbstractScreen> absScreen,sptr<AbstractScreenGroup> screenGroup,sptr<AbstractDisplay> & absDisplay)237 DisplayId AbstractDisplayController::ProcessExpandScreenDisconnected(
238     sptr<AbstractScreen> absScreen, sptr<AbstractScreenGroup> screenGroup, sptr<AbstractDisplay>& absDisplay)
239 {
240     TLOGI(WmsLogTag::DMS, "expand screen disconnect");
241     if (absScreen == nullptr || screenGroup == nullptr) {
242         TLOGE(WmsLogTag::DMS, "Invalid params as nullptr.");
243         return DISPLAY_ID_INVALID;
244     }
245     DisplayId displayId = DISPLAY_ID_INVALID;
246     for (auto iter = abstractDisplayMap_.begin(); iter != abstractDisplayMap_.end(); iter++) {
247         sptr<AbstractDisplay> abstractDisplay = iter->second;
248         if (abstractDisplay->GetAbstractScreenId() == absScreen->dmsId_) {
249             TLOGI(WmsLogTag::DMS, "expand screen disconnect, displayId: %{public}" PRIu64", screenId: %{public}" PRIu64"",
250                 displayId, abstractDisplay->GetAbstractScreenId());
251             absDisplay = abstractDisplay;
252             displayId = iter->first;
253         } else {
254             abstractDisplay->SetOffset(0, 0);
255             auto screenId = abstractDisplay->GetAbstractScreenId();
256             SetScreenOffsetInner(screenId);
257         }
258     }
259     return displayId;
260 }
261 
OnAbstractScreenChange(sptr<AbstractScreen> absScreen,DisplayChangeEvent event)262 void AbstractDisplayController::OnAbstractScreenChange(sptr<AbstractScreen> absScreen, DisplayChangeEvent event)
263 {
264     if (absScreen == nullptr) {
265         TLOGE(WmsLogTag::DMS, "OnAbstractScreenChanged::the information of the screen is wrong");
266         return;
267     }
268     TLOGI(WmsLogTag::DMS, "screen changes. id:%{public}" PRIu64"", absScreen->dmsId_);
269     if (event == DisplayChangeEvent::UPDATE_ORIENTATION) {
270         ProcessDisplayUpdateOrientation(absScreen, DisplayStateChangeType::UPDATE_ROTATION);
271     } else if (event == DisplayChangeEvent::UPDATE_ORIENTATION_FROM_WINDOW) {
272         ProcessDisplayUpdateOrientation(absScreen, DisplayStateChangeType::UPDATE_ROTATION_FROM_WINDOW);
273     } else if (event == DisplayChangeEvent::DISPLAY_SIZE_CHANGED) {
274         ProcessDisplaySizeChange(absScreen);
275     } else if (event == DisplayChangeEvent::DISPLAY_VIRTUAL_PIXEL_RATIO_CHANGED) {
276         ProcessVirtualPixelRatioChange(absScreen);
277     } else if (event == DisplayChangeEvent::UPDATE_ROTATION) {
278         ProcessDisplayRotationChange(absScreen, DisplayStateChangeType::UPDATE_ROTATION);
279     } else if (event == DisplayChangeEvent::UPDATE_ROTATION_FROM_WINDOW) {
280         ProcessDisplayRotationChange(absScreen, DisplayStateChangeType::UPDATE_ROTATION_FROM_WINDOW);
281     } else {
282         TLOGE(WmsLogTag::DMS, "unknown screen change event. id:%{public}" PRIu64" event %{public}u", absScreen->dmsId_,
283             event);
284     }
285 }
286 
ProcessDisplayRotationChange(sptr<AbstractScreen> absScreen,DisplayStateChangeType type)287 void AbstractDisplayController::ProcessDisplayRotationChange(sptr<AbstractScreen> absScreen,
288     DisplayStateChangeType type)
289 {
290     if (absScreen == nullptr) {
291         TLOGE(WmsLogTag::DMS, "absScreen is nullptr");
292         return;
293     }
294     sptr<AbstractDisplay> abstractDisplay = GetAbstractDisplayByAbsScreen(absScreen);
295     if (abstractDisplay == nullptr) {
296         return;
297     }
298     if (abstractDisplay->RequestRotation(absScreen->rotation_)) {
299         abstractDisplay->SetDisplayOrientation(
300             ScreenRotationController::ConvertRotationToDisplayOrientation(absScreen->rotation_));
301         // Notify rotation event to WMS
302         SetDisplayStateChangeListener(abstractDisplay, type);
303     }
304     sptr<DisplayInfo> displayInfo = abstractDisplay->ConvertToDisplayInfo();
305     DisplayManagerAgentController::GetInstance().OnDisplayChange(displayInfo,
306         DisplayChangeEvent::UPDATE_ROTATION);
307     ProcessDisplayCompression(absScreen);
308 }
309 
ProcessDisplayCompression(sptr<AbstractScreen> absScreen)310 void AbstractDisplayController::ProcessDisplayCompression(sptr<AbstractScreen> absScreen)
311 {
312     TLOGI(WmsLogTag::DMS, "Enter");
313     auto absDisplay = GetAbstractDisplayByAbsScreen(absScreen);
314     DisplayId defaultDisplayId = GetDefaultDisplayId();
315     if (absDisplay == nullptr || absDisplay->GetId() != defaultDisplayId) {
316         return;
317     }
318     uint32_t sizeInVp = DisplayCutoutController::GetWaterfallAreaCompressionSizeWhenHorizontal();
319     if (!DisplayCutoutController::IsWaterfallAreaCompressionEnableWhenHorizontal() || sizeInVp == 0) {
320         TLOGI(WmsLogTag::DMS, "Not enable waterfall display area compression.");
321         return;
322     }
323     auto mode = absScreen->GetActiveScreenMode();
324     if (mode == nullptr) {
325         TLOGW(WmsLogTag::DMS, "SupportedScreenModes is null");
326         return;
327     }
328     uint32_t screenHeight = mode->height_;
329     uint32_t screenWidth = mode->width_;
330     uint32_t sizeInPx = static_cast<uint32_t>(sizeInVp * absDisplay->GetVirtualPixelRatio());
331     // 4: Compression size shall less than 1/4 of the screen size.
332     if (sizeInPx >= screenHeight / 4 || sizeInPx >= screenWidth / 4) {
333         TLOGW(WmsLogTag::DMS, "Invalid value for waterfall display curved area avoid size of each sides");
334         return;
335     }
336     TLOGI(WmsLogTag::DMS, "SizeInPx: %{public}u", sizeInPx);
337     Rotation rotation = absDisplay->GetRotation();
338     bool isDefaultRotationVertical = mode->height_ > mode->width_ ? true : false;
339     if (ScreenRotationController::IsDisplayRotationHorizontal(rotation)) {
340         uint32_t offsetY = sizeInPx;
341         uint32_t totalCompressedSize = offsetY * 2; // *2 for both sides.
342         uint32_t displayHeightAfter = isDefaultRotationVertical ? mode->width_ - totalCompressedSize :
343             mode->height_ - totalCompressedSize;
344         absDisplay->SetOffsetX(0);
345         absDisplay->SetOffsetY(offsetY);
346         absDisplay->SetHeight(displayHeightAfter);
347         absDisplay->SetWaterfallDisplayCompressionStatus(true);
348     } else {
349         if (!absDisplay->GetWaterfallDisplayCompressionStatus()) {
350             return;
351         }
352         absDisplay->SetOffsetX(0);
353         absDisplay->SetOffsetY(0);
354         absDisplay->SetHeight(isDefaultRotationVertical ? mode->height_ : mode->width_);
355         absDisplay->SetWidth(isDefaultRotationVertical ? mode->width_ : mode->height_);
356         absDisplay->SetWaterfallDisplayCompressionStatus(false);
357     }
358     SetDisplayStateChangeListener(absDisplay, DisplayStateChangeType::DISPLAY_COMPRESS);
359     DisplayManagerAgentController::GetInstance().OnDisplayChange(
360         absDisplay->ConvertToDisplayInfo(), DisplayChangeEvent::DISPLAY_SIZE_CHANGED);
361 }
362 
GetAbstractDisplayByAbsScreen(sptr<AbstractScreen> absScreen)363 sptr<AbstractDisplay> AbstractDisplayController::GetAbstractDisplayByAbsScreen(sptr<AbstractScreen> absScreen)
364 {
365     if (absScreen == nullptr) {
366         TLOGE(WmsLogTag::DMS, "absScreen is invaild");
367         return nullptr;
368     }
369     sptr<AbstractScreenGroup> group = absScreen->GetGroup();
370     if (group == nullptr) {
371         TLOGE(WmsLogTag::DMS, "cannot get screen group");
372         return nullptr;
373     }
374     sptr<AbstractDisplay> abstractDisplay = nullptr;
375     {
376         std::lock_guard<std::recursive_mutex> lock(mutex_);
377         auto iter = abstractDisplayMap_.begin();
378         for (; iter != abstractDisplayMap_.end(); iter++) {
379             if (iter->second->GetAbstractScreenId() == absScreen->dmsId_) {
380                 abstractDisplay = iter->second;
381                 TLOGD(WmsLogTag::DMS, "find abstract display of the screen. display %{public}" PRIu64", screen"
382                     " %{public}" PRIu64"", abstractDisplay->GetId(), absScreen->dmsId_);
383                 break;
384             }
385         }
386     }
387     if (abstractDisplay == nullptr) {
388         if (group->combination_ == ScreenCombination::SCREEN_ALONE
389             || group->combination_ == ScreenCombination::SCREEN_EXPAND) {
390             TLOGE(WmsLogTag::DMS, "Screen combination is SCREEN_ALONE or SCREEN_EXPAND, cannot find abstract "
391                 "display of the screen");
392         } else if (group->combination_ == ScreenCombination::SCREEN_MIRROR) {
393             // If the screen cannot be found in 'abstractDisplayMap_', it means that the screen is the secondary
394             TLOGI(WmsLogTag::DMS, "It's the secondary screen of the mirrored.");
395         } else {
396             TLOGE(WmsLogTag::DMS, "Unknown combination");
397         }
398     }
399     return abstractDisplay;
400 }
401 
ProcessDisplayUpdateOrientation(sptr<AbstractScreen> absScreen,DisplayStateChangeType type)402 void AbstractDisplayController::ProcessDisplayUpdateOrientation(sptr<AbstractScreen> absScreen,
403     DisplayStateChangeType type)
404 {
405     sptr<AbstractDisplay> abstractDisplay = nullptr;
406     {
407         std::lock_guard<std::recursive_mutex> lock(mutex_);
408         auto iter = abstractDisplayMap_.begin();
409         for (; iter != abstractDisplayMap_.end(); iter++) {
410             abstractDisplay = iter->second;
411             if (abstractDisplay->GetAbstractScreenId() == absScreen->dmsId_) {
412                 TLOGD(WmsLogTag::DMS, "find abstract display of the screen. display %{public}" PRIu64", "
413                     "screen %{public}" PRIu64"", abstractDisplay->GetId(), absScreen->dmsId_);
414                 break;
415             }
416         }
417 
418         sptr<AbstractScreenGroup> group = absScreen->GetGroup();
419         if (group == nullptr) {
420             TLOGE(WmsLogTag::DMS, "cannot get screen group");
421             return;
422         }
423         if (iter == abstractDisplayMap_.end()) {
424             if (group->combination_ == ScreenCombination::SCREEN_ALONE
425                 || group->combination_ == ScreenCombination::SCREEN_EXPAND) {
426                 TLOGE(WmsLogTag::DMS, "cannot find abstract display of the screen %{public}" PRIu64"",
427                     absScreen->dmsId_);
428                 return;
429             } else if (group->combination_ == ScreenCombination::SCREEN_MIRROR) {
430                 // If the screen cannot be found in 'abstractDisplayMap_', it means that the screen is the secondary
431                 TLOGI(WmsLogTag::DMS, "It's the secondary screen of the mirrored.");
432                 return;
433             } else {
434                 TLOGE(WmsLogTag::DMS, "Unknown combination");
435                 return;
436             }
437         }
438     }
439     abstractDisplay->SetOrientation(absScreen->orientation_);
440     if (abstractDisplay->RequestRotation(absScreen->rotation_)) {
441         // Notify rotation event to WMS
442         SetDisplayStateChangeListener(abstractDisplay, type);
443     }
444 }
445 
ProcessDisplaySizeChange(sptr<AbstractScreen> absScreen)446 void AbstractDisplayController::ProcessDisplaySizeChange(sptr<AbstractScreen> absScreen)
447 {
448     HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:ProcessDisplaySizeChange(%" PRIu64")", absScreen->dmsId_);
449     sptr<SupportedScreenModes> info = absScreen->GetActiveScreenMode();
450     if (info == nullptr) {
451         TLOGE(WmsLogTag::DMS, "cannot get active screen info.");
452         return;
453     }
454 
455     std::map<DisplayId, sptr<AbstractDisplay>> matchedDisplays;
456     {
457         std::lock_guard<std::recursive_mutex> lock(mutex_);
458         for (auto iter = abstractDisplayMap_.begin(); iter != abstractDisplayMap_.end(); ++iter) {
459             sptr<AbstractDisplay> absDisplay = iter->second;
460             if (absDisplay == nullptr || absDisplay->GetAbstractScreenId() != absScreen->dmsId_) {
461                 continue;
462             }
463             if (UpdateDisplaySize(absDisplay, info, absScreen->startPoint_)) {
464                 matchedDisplays.insert(std::make_pair(iter->first, iter->second));
465             }
466         }
467     }
468 
469     TLOGI(WmsLogTag::DMS, "Size of matchedDisplays %{public}zu", matchedDisplays.size());
470     for (auto iter = matchedDisplays.begin(); iter != matchedDisplays.end(); ++iter) {
471         TLOGI(WmsLogTag::DMS, "Notify display size change. Id %{public}" PRIu64"", iter->first);
472         sptr<AbstractDisplay> abstractDisplay = iter->second;
473         SetDisplayStateChangeListener(abstractDisplay, DisplayStateChangeType::SIZE_CHANGE);
474         DisplayManagerAgentController::GetInstance().OnDisplayChange(
475             abstractDisplay->ConvertToDisplayInfo(), DisplayChangeEvent::DISPLAY_SIZE_CHANGED);
476     }
477 }
478 
UpdateDisplaySize(sptr<AbstractDisplay> absDisplay,sptr<SupportedScreenModes> info,Point offset)479 bool AbstractDisplayController::UpdateDisplaySize(sptr<AbstractDisplay> absDisplay, sptr<SupportedScreenModes> info,
480     Point offset)
481 {
482     if (absDisplay == nullptr) {
483         TLOGE(WmsLogTag::DMS, "invalid params.");
484         return false;
485     }
486 
487     bool changed = false;
488     if (info) {
489         auto rotation = absDisplay->GetRotation();
490         int32_t width = 0;
491         int32_t height = 0;
492         if (rotation == Rotation::ROTATION_90 || rotation == Rotation::ROTATION_270) {
493             width = absDisplay->GetHeight();
494             height = absDisplay->GetWidth();
495         } else {
496             width = absDisplay->GetWidth();
497             height = absDisplay->GetHeight();
498         }
499 
500         if (info->width_ == static_cast<uint32_t>(width) &&
501             info->height_ == static_cast<uint32_t>(height)) {
502             TLOGD(WmsLogTag::DMS, "keep display size. display:%{public}" PRIu64"", absDisplay->GetId());
503         } else {
504             TLOGD(WmsLogTag::DMS, "Reset H&W. id %{public}" PRIu64", size: %{public}d %{public}d",
505                 absDisplay->GetId(), info->width_, info->height_);
506             absDisplay->SetWidth(info->width_);
507             absDisplay->SetHeight(info->height_);
508             changed = true;
509         }
510     } else {
511         TLOGE(WmsLogTag::DMS, "mode info is null");
512     }
513 
514     if (offset.posX_ == absDisplay->GetOffsetX() &&
515         offset.posY_ == absDisplay->GetOffsetY()) {
516         TLOGD(WmsLogTag::DMS, "keep display offset. display:%{public}" PRIu64"", absDisplay->GetId());
517     } else {
518         TLOGD(WmsLogTag::DMS, "Reset offset. id %{public}" PRIu64", size: %{public}d %{public}d",
519             absDisplay->GetId(), offset.posX_, offset.posY_);
520         absDisplay->SetOffsetX(offset.posX_);
521         absDisplay->SetOffsetY(offset.posY_);
522         changed = true;
523     }
524 
525     return changed;
526 }
527 
ProcessVirtualPixelRatioChange(sptr<AbstractScreen> absScreen)528 void AbstractDisplayController::ProcessVirtualPixelRatioChange(sptr<AbstractScreen> absScreen)
529 {
530     sptr<AbstractDisplay> abstractDisplay = nullptr;
531     {
532         std::lock_guard<std::recursive_mutex> lock(mutex_);
533         auto iter = abstractDisplayMap_.begin();
534         for (; iter != abstractDisplayMap_.end(); iter++) {
535             abstractDisplay = iter->second;
536             if (abstractDisplay->GetAbstractScreenId() == absScreen->dmsId_) {
537                 TLOGD(WmsLogTag::DMS, "find abstract display of the screen. display %{public}" PRIu64", screen "
538                     "%{public}" PRIu64"", abstractDisplay->GetId(), absScreen->dmsId_);
539                 break;
540             }
541         }
542     }
543     if (abstractDisplay == nullptr) {
544         TLOGE(WmsLogTag::DMS, "Failed to find abstract display of the screen.");
545         return;
546     }
547     abstractDisplay->SetVirtualPixelRatio(absScreen->virtualPixelRatio_);
548     // Notify virtual pixel ratio change event to WMS
549     SetDisplayStateChangeListener(abstractDisplay, DisplayStateChangeType::VIRTUAL_PIXEL_RATIO_CHANGE);
550     // Notify virtual pixel ratio change event to DisplayManager
551     DisplayManagerAgentController::GetInstance().OnDisplayChange(abstractDisplay->ConvertToDisplayInfo(),
552         DisplayChangeEvent::DISPLAY_VIRTUAL_PIXEL_RATIO_CHANGED);
553 }
554 
BindAloneScreenLocked(sptr<AbstractScreen> realAbsScreen)555 void AbstractDisplayController::BindAloneScreenLocked(sptr<AbstractScreen> realAbsScreen)
556 {
557     if (realAbsScreen == nullptr) {
558         TLOGE(WmsLogTag::DMS, "BindAloneScreenLocked failed, realAbsScreen is nullptr");
559         return;
560     }
561     ScreenId defaultScreenId = abstractScreenController_->GetDefaultAbstractScreenId();
562     if (defaultScreenId != SCREEN_ID_INVALID) {
563         if (defaultScreenId != realAbsScreen->dmsId_) {
564             TLOGE(WmsLogTag::DMS, "The first real screen should be default for Phone. %{public}" PRIu64"",
565                 realAbsScreen->dmsId_);
566             return;
567         }
568         sptr<SupportedScreenModes> info = realAbsScreen->GetActiveScreenMode();
569         if (info == nullptr) {
570             TLOGE(WmsLogTag::DMS, "bind alone screen error, cannot get info.");
571             return;
572         }
573         if (dummyDisplay_ == nullptr) {
574             DisplayId displayId = displayCount_.fetch_add(1);
575             sptr<AbstractDisplay> display = new(std::nothrow) AbstractDisplay(displayId, info, realAbsScreen);
576             if (display == nullptr) {
577                 TLOGE(WmsLogTag::DMS, "create display failed");
578                 return;
579             }
580 
581             abstractDisplayMap_.insert((std::make_pair(display->GetId(), display)));
582             TLOGI(WmsLogTag::DMS, "create display for new screen. screen:%{public}" PRIu64", "
583                 "display:%{public}" PRIu64"", realAbsScreen->dmsId_, display->GetId());
584             DisplayManagerAgentController::GetInstance().OnDisplayCreate(display->ConvertToDisplayInfo());
585             SetDisplayStateChangeListener(display, DisplayStateChangeType::CREATE);
586         } else {
587             TLOGI(WmsLogTag::DMS, "bind display for new screen. screen:%{public}" PRIu64", display:%{public}" PRIu64"",
588                 realAbsScreen->dmsId_, dummyDisplay_->GetId());
589             bool updateFlag = static_cast<uint32_t>(dummyDisplay_->GetHeight()) == info->height_
590                     && static_cast<uint32_t>(dummyDisplay_->GetWidth()) == info->width_;
591             dummyDisplay_->BindAbstractScreen(abstractScreenController_->GetAbstractScreen(realAbsScreen->dmsId_));
592             if (updateFlag) {
593                 DisplayManagerAgentController::GetInstance().OnDisplayCreate(dummyDisplay_->ConvertToDisplayInfo());
594             }
595             dummyDisplay_ = nullptr;
596         }
597     } else {
598         TLOGE(WmsLogTag::DMS, "The first real screen should be default screen for Phone. %{public}" PRIu64"",
599             realAbsScreen->dmsId_);
600     }
601 }
602 
AddScreenToMirrorLocked(sptr<AbstractScreen> absScreen)603 void AbstractDisplayController::AddScreenToMirrorLocked(sptr<AbstractScreen> absScreen)
604 {
605     TLOGI(WmsLogTag::DMS, "bind display to mirror. screen:%{public}" PRIu64"", absScreen->dmsId_);
606 }
607 
AddScreenToExpandLocked(sptr<AbstractScreen> absScreen)608 void AbstractDisplayController::AddScreenToExpandLocked(sptr<AbstractScreen> absScreen)
609 {
610     if (absScreen == nullptr) {
611         TLOGE(WmsLogTag::DMS, "AddScreenToExpandLocked failed, absScreen is nullptr");
612         return;
613     }
614     for (auto iter = abstractDisplayMap_.begin(); iter != abstractDisplayMap_.end(); iter++) {
615         sptr<AbstractDisplay> abstractDisplay = iter->second;
616         if (abstractDisplay->GetAbstractScreenId() == absScreen->dmsId_) {
617             TLOGE(WmsLogTag::DMS, "error, screenId: %{public}" PRIu64" already has corresponding display",
618                 absScreen->dmsId_);
619             return;
620         }
621     }
622     TLOGI(WmsLogTag::DMS, "bind display to expand. screen:%{public}" PRIu64"", absScreen->dmsId_);
623     sptr<SupportedScreenModes> info;
624     ScreenId defaultScreenId = abstractScreenController_->GetDefaultAbstractScreenId();
625     sptr<AbstractScreen> defaultScreen = abstractScreenController_->GetAbstractScreen(defaultScreenId);
626     if (absScreen->type_ == ScreenType::VIRTUAL) {
627         TLOGI(WmsLogTag::DMS, "screen type is virtual, use default screen info");
628         if (defaultScreen == nullptr) {
629             TLOGE(WmsLogTag::DMS, "bind display error, cannot get defaultScreen.");
630             return;
631         }
632         info = defaultScreen->GetActiveScreenMode();
633     } else {
634         TLOGI(WmsLogTag::DMS, "screen type is not virtual, get this screen info");
635         info = absScreen->GetActiveScreenMode();
636     }
637     if (info == nullptr) {
638         TLOGE(WmsLogTag::DMS, "bind display error, cannot get info.");
639         return;
640     }
641     DisplayId displayId = displayCount_.fetch_add(1);
642     sptr<AbstractDisplay> display = new AbstractDisplay(displayId, info, absScreen);
643     Point point = abstractScreenController_->GetAbstractScreenGroup(absScreen->groupDmsId_)->
644         GetChildPosition(absScreen->dmsId_);
645     display->SetOffset(point.posX_, point.posY_);
646     abstractDisplayMap_.insert((std::make_pair(display->GetId(), display)));
647     TLOGI(WmsLogTag::DMS, "create display for new screen. screen:%{public}" PRIu64", display:%{public}" PRIu64"",
648         absScreen->dmsId_, display->GetId());
649     DisplayManagerAgentController::GetInstance().OnDisplayCreate(display->ConvertToDisplayInfo());
650     SetDisplayStateChangeListener(display, DisplayStateChangeType::CREATE);
651 }
652 
SetFreeze(std::vector<DisplayId> displayIds,bool toFreeze)653 void AbstractDisplayController::SetFreeze(std::vector<DisplayId> displayIds, bool toFreeze)
654 {
655     HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:SetAllFreeze");
656     DisplayStateChangeType type = toFreeze ? DisplayStateChangeType::FREEZE : DisplayStateChangeType::UNFREEZE;
657     DisplayChangeEvent event
658         = toFreeze ? DisplayChangeEvent::DISPLAY_FREEZED : DisplayChangeEvent::DISPLAY_UNFREEZED;
659     for (DisplayId displayId : displayIds) {
660         sptr<AbstractDisplay> abstractDisplay;
661         HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:SetFreeze(%" PRIu64")", displayId);
662         {
663             TLOGI(WmsLogTag::DMS, "setfreeze display %{public}" PRIu64"", displayId);
664             std::lock_guard<std::recursive_mutex> lock(mutex_);
665             auto iter = abstractDisplayMap_.find(displayId);
666             if (iter == abstractDisplayMap_.end()) {
667                 TLOGE(WmsLogTag::DMS, "setfreeze fail, cannot get display %{public}" PRIu64"", displayId);
668                 continue;
669             }
670             abstractDisplay = iter->second;
671             FreezeFlag curFlag = abstractDisplay->GetFreezeFlag();
672             if ((toFreeze && (curFlag == FreezeFlag::FREEZING))
673                 || (!toFreeze && (curFlag == FreezeFlag::UNFREEZING))) {
674                 TLOGE(WmsLogTag::DMS, "setfreeze fail, display %{public}" PRIu64" freezeflag is %{public}u",
675                     displayId, curFlag);
676                 continue;
677             }
678             FreezeFlag flag = toFreeze ? FreezeFlag::FREEZING : FreezeFlag::UNFREEZING;
679             abstractDisplay->SetFreezeFlag(flag);
680         }
681 
682         // Notify freeze event to WMS
683         SetDisplayStateChangeListener(abstractDisplay, type);
684         // Notify freeze event to DisplayManager
685         DisplayManagerAgentController::GetInstance().OnDisplayChange(abstractDisplay->ConvertToDisplayInfo(), event);
686     }
687 }
688 
GetAllDisplayInfoOfGroup(sptr<DisplayInfo> info)689 std::map<DisplayId, sptr<DisplayInfo>> AbstractDisplayController::GetAllDisplayInfoOfGroup(sptr<DisplayInfo> info)
690 {
691     ScreenId screenGroupId = info->GetScreenGroupId();
692     std::map<DisplayId, sptr<DisplayInfo>> displayInfoMap;
693     std::lock_guard<std::recursive_mutex> lock(mutex_);
694     for (const auto& iter : abstractDisplayMap_) {
695         sptr<AbstractDisplay> display = iter.second;
696         if (display->GetAbstractScreenGroupId() == screenGroupId) {
697             displayInfoMap.insert(std::make_pair(display->GetId(), display->ConvertToDisplayInfo()));
698         }
699     }
700     return displayInfoMap;
701 }
702 
SetDisplayStateChangeListener(sptr<AbstractDisplay> abstractDisplay,DisplayStateChangeType type)703 void AbstractDisplayController::SetDisplayStateChangeListener(
704     sptr<AbstractDisplay> abstractDisplay, DisplayStateChangeType type)
705 {
706     ScreenId defaultDisplayId = GetDefaultDisplayId();
707     std::map<DisplayId, sptr<DisplayInfo>> displayInfoMap = GetAllDisplayInfoOfGroup(
708         abstractDisplay->ConvertToDisplayInfo());
709     displayStateChangeListener_(defaultDisplayId, abstractDisplay->ConvertToDisplayInfo(), displayInfoMap, type);
710 }
711 
GetDefaultDisplayId()712 DisplayId AbstractDisplayController::GetDefaultDisplayId()
713 {
714     DisplayId defaultDisplayId = DISPLAY_ID_INVALID;
715     ScreenId defaultScreenId = abstractScreenController_->GetDefaultAbstractScreenId();
716     sptr<AbstractDisplay> defaultDisplay = GetAbstractDisplayByScreen(defaultScreenId);
717     if (defaultDisplay != nullptr) {
718         defaultDisplayId = defaultDisplay->GetId();
719     }
720     return defaultDisplayId;
721 }
722 
SetScreenOffsetInner(ScreenId screenId)723 bool AbstractDisplayController::SetScreenOffsetInner(ScreenId screenId)
724 {
725     sptr<AbstractScreen> absScreen = abstractScreenController_->GetAbstractScreen(screenId);
726     if (absScreen == nullptr) {
727         TLOGE(WmsLogTag::DMS, "did not find screen:%{public}" PRIu64, screenId);
728         return false;
729     }
730     TLOGI(WmsLogTag::DMS, "screenId = %{public}" PRIu64 " rsId = %{public}" PRIu64, screenId, absScreen->rsId_);
731     RSInterfaces::GetInstance().SetScreenOffset(absScreen->rsId_, 0, 0);
732     return true;
733 }
734 } // namespace OHOS::Rosen