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