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     sptr<AbstractDisplay> abstractDisplay = GetAbstractDisplayByAbsScreen(absScreen);
292     if (abstractDisplay == nullptr) {
293         return;
294     }
295     if (abstractDisplay->RequestRotation(absScreen->rotation_)) {
296         abstractDisplay->SetDisplayOrientation(
297             ScreenRotationController::ConvertRotationToDisplayOrientation(absScreen->rotation_));
298         // Notify rotation event to WMS
299         SetDisplayStateChangeListener(abstractDisplay, type);
300     }
301     sptr<DisplayInfo> displayInfo = abstractDisplay->ConvertToDisplayInfo();
302     DisplayManagerAgentController::GetInstance().OnDisplayChange(displayInfo,
303         DisplayChangeEvent::UPDATE_ROTATION);
304     ProcessDisplayCompression(absScreen);
305 }
306 
ProcessDisplayCompression(sptr<AbstractScreen> absScreen)307 void AbstractDisplayController::ProcessDisplayCompression(sptr<AbstractScreen> absScreen)
308 {
309     WLOGFI("Enter");
310     auto absDisplay = GetAbstractDisplayByAbsScreen(absScreen);
311     DisplayId defaultDisplayId = GetDefaultDisplayId();
312     if (absDisplay == nullptr || absDisplay->GetId() != defaultDisplayId) {
313         return;
314     }
315     uint32_t sizeInVp = DisplayCutoutController::GetWaterfallAreaCompressionSizeWhenHorizontal();
316     if (!DisplayCutoutController::IsWaterfallAreaCompressionEnableWhenHorizontal() || sizeInVp == 0) {
317         WLOGFI("Not enable waterfall display area compression.");
318         return;
319     }
320     auto mode = absScreen->GetActiveScreenMode();
321     if (mode == nullptr) {
322         WLOGFW("SupportedScreenModes is null");
323         return;
324     }
325     uint32_t screenHeight = mode->height_;
326     uint32_t screenWidth = mode->width_;
327     uint32_t sizeInPx = static_cast<uint32_t>(sizeInVp * absDisplay->GetVirtualPixelRatio());
328     // 4: Compression size shall less than 1/4 of the screen size.
329     if (sizeInPx >= screenHeight / 4 || sizeInPx >= screenWidth / 4) {
330         WLOGFW("Invalid value for waterfall display curved area avoid size of each sides");
331         return;
332     }
333     WLOGFI("SizeInPx: %{public}u", sizeInPx);
334     Rotation rotation = absDisplay->GetRotation();
335     bool isDefaultRotationVertical = mode->height_ > mode->width_ ? true : false;
336     if (ScreenRotationController::IsDisplayRotationHorizontal(rotation)) {
337         uint32_t offsetY = sizeInPx;
338         uint32_t totalCompressedSize = offsetY * 2; // *2 for both sides.
339         uint32_t displayHeightAfter = isDefaultRotationVertical ? mode->width_ - totalCompressedSize :
340             mode->height_ - totalCompressedSize;
341         absDisplay->SetOffsetX(0);
342         absDisplay->SetOffsetY(offsetY);
343         absDisplay->SetHeight(displayHeightAfter);
344         absDisplay->SetWaterfallDisplayCompressionStatus(true);
345     } else {
346         if (!absDisplay->GetWaterfallDisplayCompressionStatus()) {
347             return;
348         }
349         absDisplay->SetOffsetX(0);
350         absDisplay->SetOffsetY(0);
351         absDisplay->SetHeight(isDefaultRotationVertical ? mode->height_ : mode->width_);
352         absDisplay->SetWidth(isDefaultRotationVertical ? mode->width_ : mode->height_);
353         absDisplay->SetWaterfallDisplayCompressionStatus(false);
354     }
355     SetDisplayStateChangeListener(absDisplay, DisplayStateChangeType::DISPLAY_COMPRESS);
356     DisplayManagerAgentController::GetInstance().OnDisplayChange(
357         absDisplay->ConvertToDisplayInfo(), DisplayChangeEvent::DISPLAY_SIZE_CHANGED);
358 }
359 
GetAbstractDisplayByAbsScreen(sptr<AbstractScreen> absScreen)360 sptr<AbstractDisplay> AbstractDisplayController::GetAbstractDisplayByAbsScreen(sptr<AbstractScreen> absScreen)
361 {
362     sptr<AbstractDisplay> abstractDisplay = nullptr;
363     std::lock_guard<std::recursive_mutex> lock(mutex_);
364     auto iter = abstractDisplayMap_.begin();
365     for (; iter != abstractDisplayMap_.end(); iter++) {
366         if (iter->second->GetAbstractScreenId() == absScreen->dmsId_) {
367             abstractDisplay = iter->second;
368             WLOGFD("find abstract display of the screen. display %{public}" PRIu64", screen %{public}" PRIu64"",
369                 abstractDisplay->GetId(), absScreen->dmsId_);
370             break;
371         }
372     }
373     sptr<AbstractScreenGroup> group = absScreen->GetGroup();
374     if (group == nullptr) {
375         WLOGFE("cannot get screen group");
376         return nullptr;
377     }
378     if (iter == abstractDisplayMap_.end()) {
379         if (group->combination_ == ScreenCombination::SCREEN_ALONE
380             || group->combination_ == ScreenCombination::SCREEN_EXPAND) {
381             WLOGFE("Screen combination is SCREEN_ALONE or SCREEN_EXPAND, cannot find abstract display of the screen");
382         } else if (group->combination_ == ScreenCombination::SCREEN_MIRROR) {
383             // If the screen cannot be found in 'abstractDisplayMap_', it means that the screen is the secondary
384             WLOGFI("It's the secondary screen of the mirrored.");
385         } else {
386             WLOGFE("Unknown combination");
387         }
388         return nullptr;
389     }
390     return abstractDisplay;
391 }
392 
ProcessDisplayUpdateOrientation(sptr<AbstractScreen> absScreen,DisplayStateChangeType type)393 void AbstractDisplayController::ProcessDisplayUpdateOrientation(sptr<AbstractScreen> absScreen,
394     DisplayStateChangeType type)
395 {
396     sptr<AbstractDisplay> abstractDisplay = nullptr;
397     {
398         std::lock_guard<std::recursive_mutex> lock(mutex_);
399         auto iter = abstractDisplayMap_.begin();
400         for (; iter != abstractDisplayMap_.end(); iter++) {
401             abstractDisplay = iter->second;
402             if (abstractDisplay->GetAbstractScreenId() == absScreen->dmsId_) {
403                 WLOGFD("find abstract display of the screen. display %{public}" PRIu64", screen %{public}" PRIu64"",
404                     abstractDisplay->GetId(), absScreen->dmsId_);
405                 break;
406             }
407         }
408 
409         sptr<AbstractScreenGroup> group = absScreen->GetGroup();
410         if (group == nullptr) {
411             WLOGFE("cannot get screen group");
412             return;
413         }
414         if (iter == abstractDisplayMap_.end()) {
415             if (group->combination_ == ScreenCombination::SCREEN_ALONE
416                 || group->combination_ == ScreenCombination::SCREEN_EXPAND) {
417                 WLOGFE("cannot find abstract display of the screen %{public}" PRIu64"", absScreen->dmsId_);
418                 return;
419             } else if (group->combination_ == ScreenCombination::SCREEN_MIRROR) {
420                 // If the screen cannot be found in 'abstractDisplayMap_', it means that the screen is the secondary
421                 WLOGFI("It's the secondary screen of the mirrored.");
422                 return;
423             } else {
424                 WLOGFE("Unknown combination");
425                 return;
426             }
427         }
428     }
429     abstractDisplay->SetOrientation(absScreen->orientation_);
430     if (abstractDisplay->RequestRotation(absScreen->rotation_)) {
431         // Notify rotation event to WMS
432         SetDisplayStateChangeListener(abstractDisplay, type);
433     }
434 }
435 
ProcessDisplaySizeChange(sptr<AbstractScreen> absScreen)436 void AbstractDisplayController::ProcessDisplaySizeChange(sptr<AbstractScreen> absScreen)
437 {
438     HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:ProcessDisplaySizeChange(%" PRIu64")", absScreen->dmsId_);
439     sptr<SupportedScreenModes> info = absScreen->GetActiveScreenMode();
440     if (info == nullptr) {
441         WLOGE("cannot get active screen info.");
442         return;
443     }
444 
445     std::map<DisplayId, sptr<AbstractDisplay>> matchedDisplays;
446     {
447         std::lock_guard<std::recursive_mutex> lock(mutex_);
448         for (auto iter = abstractDisplayMap_.begin(); iter != abstractDisplayMap_.end(); ++iter) {
449             sptr<AbstractDisplay> absDisplay = iter->second;
450             if (absDisplay == nullptr || absDisplay->GetAbstractScreenId() != absScreen->dmsId_) {
451                 continue;
452             }
453             if (UpdateDisplaySize(absDisplay, info, absScreen->startPoint_)) {
454                 matchedDisplays.insert(std::make_pair(iter->first, iter->second));
455             }
456         }
457     }
458 
459     WLOGFI("Size of matchedDisplays %{public}zu", matchedDisplays.size());
460     for (auto iter = matchedDisplays.begin(); iter != matchedDisplays.end(); ++iter) {
461         WLOGFI("Notify display size change. Id %{public}" PRIu64"", iter->first);
462         sptr<AbstractDisplay> abstractDisplay = iter->second;
463         SetDisplayStateChangeListener(abstractDisplay, DisplayStateChangeType::SIZE_CHANGE);
464         DisplayManagerAgentController::GetInstance().OnDisplayChange(
465             abstractDisplay->ConvertToDisplayInfo(), DisplayChangeEvent::DISPLAY_SIZE_CHANGED);
466     }
467 }
468 
UpdateDisplaySize(sptr<AbstractDisplay> absDisplay,sptr<SupportedScreenModes> info,Point offset)469 bool AbstractDisplayController::UpdateDisplaySize(sptr<AbstractDisplay> absDisplay, sptr<SupportedScreenModes> info,
470     Point offset)
471 {
472     if (absDisplay == nullptr) {
473         WLOGFE("invalid params.");
474         return false;
475     }
476 
477     bool changed = false;
478     if (info) {
479         auto rotation = absDisplay->GetRotation();
480         int32_t width = 0;
481         int32_t height = 0;
482         if (rotation == Rotation::ROTATION_90 || rotation == Rotation::ROTATION_270) {
483             width = absDisplay->GetHeight();
484             height = absDisplay->GetWidth();
485         } else {
486             width = absDisplay->GetWidth();
487             height = absDisplay->GetHeight();
488         }
489 
490         if (info->width_ == static_cast<uint32_t>(width) &&
491             info->height_ == static_cast<uint32_t>(height)) {
492             WLOGFD("keep display size. display:%{public}" PRIu64"", absDisplay->GetId());
493         } else {
494             WLOGFD("Reset H&W. id %{public}" PRIu64", size: %{public}d %{public}d",
495                 absDisplay->GetId(), info->width_, info->height_);
496             absDisplay->SetWidth(info->width_);
497             absDisplay->SetHeight(info->height_);
498             changed = true;
499         }
500     } else {
501         WLOGFE("mode info is null");
502     }
503 
504     if (offset.posX_ == absDisplay->GetOffsetX() &&
505         offset.posY_ == absDisplay->GetOffsetY()) {
506         WLOGFD("keep display offset. display:%{public}" PRIu64"", absDisplay->GetId());
507     } else {
508         WLOGFD("Reset offset. id %{public}" PRIu64", size: %{public}d %{public}d",
509             absDisplay->GetId(), offset.posX_, offset.posY_);
510         absDisplay->SetOffsetX(offset.posX_);
511         absDisplay->SetOffsetY(offset.posY_);
512         changed = true;
513     }
514 
515     return changed;
516 }
517 
ProcessVirtualPixelRatioChange(sptr<AbstractScreen> absScreen)518 void AbstractDisplayController::ProcessVirtualPixelRatioChange(sptr<AbstractScreen> absScreen)
519 {
520     sptr<AbstractDisplay> abstractDisplay = nullptr;
521     {
522         std::lock_guard<std::recursive_mutex> lock(mutex_);
523         auto iter = abstractDisplayMap_.begin();
524         for (; iter != abstractDisplayMap_.end(); iter++) {
525             abstractDisplay = iter->second;
526             if (abstractDisplay->GetAbstractScreenId() == absScreen->dmsId_) {
527                 WLOGFD("find abstract display of the screen. display %{public}" PRIu64", screen %{public}" PRIu64"",
528                     abstractDisplay->GetId(), absScreen->dmsId_);
529                 break;
530             }
531         }
532     }
533     if (abstractDisplay == nullptr) {
534         WLOGE("Failed to find abstract display of the screen.");
535         return;
536     }
537     abstractDisplay->SetVirtualPixelRatio(absScreen->virtualPixelRatio_);
538     // Notify virtual pixel ratio change event to WMS
539     SetDisplayStateChangeListener(abstractDisplay, DisplayStateChangeType::VIRTUAL_PIXEL_RATIO_CHANGE);
540     // Notify virtual pixel ratio change event to DisplayManager
541     DisplayManagerAgentController::GetInstance().OnDisplayChange(abstractDisplay->ConvertToDisplayInfo(),
542         DisplayChangeEvent::DISPLAY_VIRTUAL_PIXEL_RATIO_CHANGED);
543 }
544 
BindAloneScreenLocked(sptr<AbstractScreen> realAbsScreen)545 void AbstractDisplayController::BindAloneScreenLocked(sptr<AbstractScreen> realAbsScreen)
546 {
547     if (realAbsScreen == nullptr) {
548         WLOGE("BindAloneScreenLocked failed, realAbsScreen is nullptr");
549         return;
550     }
551     ScreenId defaultScreenId = abstractScreenController_->GetDefaultAbstractScreenId();
552     if (defaultScreenId != SCREEN_ID_INVALID) {
553         if (defaultScreenId != realAbsScreen->dmsId_) {
554             WLOGE("The first real screen should be default for Phone. %{public}" PRIu64"", realAbsScreen->dmsId_);
555             return;
556         }
557         sptr<SupportedScreenModes> info = realAbsScreen->GetActiveScreenMode();
558         if (info == nullptr) {
559             WLOGE("bind alone screen error, cannot get info.");
560             return;
561         }
562         if (dummyDisplay_ == nullptr) {
563             DisplayId displayId = displayCount_.fetch_add(1);
564             sptr<AbstractDisplay> display = new(std::nothrow) AbstractDisplay(displayId, info, realAbsScreen);
565             if (display == nullptr) {
566                 WLOGFE("create display failed");
567                 return;
568             }
569 
570             abstractDisplayMap_.insert((std::make_pair(display->GetId(), display)));
571             WLOGI("create display for new screen. screen:%{public}" PRIu64", display:%{public}" PRIu64"",
572                 realAbsScreen->dmsId_, display->GetId());
573             DisplayManagerAgentController::GetInstance().OnDisplayCreate(display->ConvertToDisplayInfo());
574             SetDisplayStateChangeListener(display, DisplayStateChangeType::CREATE);
575         } else {
576             WLOGI("bind display for new screen. screen:%{public}" PRIu64", display:%{public}" PRIu64"",
577                 realAbsScreen->dmsId_, dummyDisplay_->GetId());
578             bool updateFlag = static_cast<uint32_t>(dummyDisplay_->GetHeight()) == info->height_
579                     && static_cast<uint32_t>(dummyDisplay_->GetWidth()) == info->width_;
580             dummyDisplay_->BindAbstractScreen(abstractScreenController_->GetAbstractScreen(realAbsScreen->dmsId_));
581             if (updateFlag) {
582                 DisplayManagerAgentController::GetInstance().OnDisplayCreate(dummyDisplay_->ConvertToDisplayInfo());
583             }
584             dummyDisplay_ = nullptr;
585         }
586     } else {
587         WLOGE("The first real screen should be default screen for Phone. %{public}" PRIu64"", realAbsScreen->dmsId_);
588     }
589 }
590 
AddScreenToMirrorLocked(sptr<AbstractScreen> absScreen)591 void AbstractDisplayController::AddScreenToMirrorLocked(sptr<AbstractScreen> absScreen)
592 {
593     WLOGI("bind display to mirror. screen:%{public}" PRIu64"", absScreen->dmsId_);
594 }
595 
AddScreenToExpandLocked(sptr<AbstractScreen> absScreen)596 void AbstractDisplayController::AddScreenToExpandLocked(sptr<AbstractScreen> absScreen)
597 {
598     if (absScreen == nullptr) {
599         WLOGE("AddScreenToExpandLocked failed, absScreen is nullptr");
600         return;
601     }
602     for (auto iter = abstractDisplayMap_.begin(); iter != abstractDisplayMap_.end(); iter++) {
603         sptr<AbstractDisplay> abstractDisplay = iter->second;
604         if (abstractDisplay->GetAbstractScreenId() == absScreen->dmsId_) {
605             WLOGE("error, screenId: %{public}" PRIu64" already has corresponding display",
606                 absScreen->dmsId_);
607             return;
608         }
609     }
610     WLOGI("bind display to expand. screen:%{public}" PRIu64"", absScreen->dmsId_);
611     sptr<SupportedScreenModes> info;
612     ScreenId defaultScreenId = abstractScreenController_->GetDefaultAbstractScreenId();
613     sptr<AbstractScreen> defaultScreen = abstractScreenController_->GetAbstractScreen(defaultScreenId);
614     if (absScreen->type_ == ScreenType::VIRTUAL) {
615         WLOGI("screen type is virtual, use default screen info");
616         if (defaultScreen == nullptr) {
617             WLOGE("bind display error, cannot get defaultScreen.");
618             return;
619         }
620         info = defaultScreen->GetActiveScreenMode();
621     } else {
622         WLOGI("screen type is not virtual, get this screen info");
623         info = absScreen->GetActiveScreenMode();
624     }
625     if (info == nullptr) {
626         WLOGE("bind display error, cannot get info.");
627         return;
628     }
629     DisplayId displayId = displayCount_.fetch_add(1);
630     sptr<AbstractDisplay> display = new AbstractDisplay(displayId, info, absScreen);
631     Point point = abstractScreenController_->GetAbstractScreenGroup(absScreen->groupDmsId_)->
632         GetChildPosition(absScreen->dmsId_);
633     display->SetOffset(point.posX_, point.posY_);
634     abstractDisplayMap_.insert((std::make_pair(display->GetId(), display)));
635     WLOGI("create display for new screen. screen:%{public}" PRIu64", display:%{public}" PRIu64"",
636         absScreen->dmsId_, display->GetId());
637     DisplayManagerAgentController::GetInstance().OnDisplayCreate(display->ConvertToDisplayInfo());
638     SetDisplayStateChangeListener(display, DisplayStateChangeType::CREATE);
639 }
640 
SetFreeze(std::vector<DisplayId> displayIds,bool toFreeze)641 void AbstractDisplayController::SetFreeze(std::vector<DisplayId> displayIds, bool toFreeze)
642 {
643     HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:SetAllFreeze");
644     DisplayStateChangeType type = toFreeze ? DisplayStateChangeType::FREEZE : DisplayStateChangeType::UNFREEZE;
645     DisplayChangeEvent event
646         = toFreeze ? DisplayChangeEvent::DISPLAY_FREEZED : DisplayChangeEvent::DISPLAY_UNFREEZED;
647     for (DisplayId displayId : displayIds) {
648         sptr<AbstractDisplay> abstractDisplay;
649         HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:SetFreeze(%" PRIu64")", displayId);
650         {
651             WLOGI("setfreeze display %{public}" PRIu64"", displayId);
652             std::lock_guard<std::recursive_mutex> lock(mutex_);
653             auto iter = abstractDisplayMap_.find(displayId);
654             if (iter == abstractDisplayMap_.end()) {
655                 WLOGE("setfreeze fail, cannot get display %{public}" PRIu64"", displayId);
656                 continue;
657             }
658             abstractDisplay = iter->second;
659             FreezeFlag curFlag = abstractDisplay->GetFreezeFlag();
660             if ((toFreeze && (curFlag == FreezeFlag::FREEZING))
661                 || (!toFreeze && (curFlag == FreezeFlag::UNFREEZING))) {
662                 WLOGE("setfreeze fail, display %{public}" PRIu64" freezeflag is %{public}u",
663                     displayId, curFlag);
664                 continue;
665             }
666             FreezeFlag flag = toFreeze ? FreezeFlag::FREEZING : FreezeFlag::UNFREEZING;
667             abstractDisplay->SetFreezeFlag(flag);
668         }
669 
670         // Notify freeze event to WMS
671         SetDisplayStateChangeListener(abstractDisplay, type);
672         // Notify freeze event to DisplayManager
673         DisplayManagerAgentController::GetInstance().OnDisplayChange(abstractDisplay->ConvertToDisplayInfo(), event);
674     }
675 }
676 
GetAllDisplayInfoOfGroup(sptr<DisplayInfo> info)677 std::map<DisplayId, sptr<DisplayInfo>> AbstractDisplayController::GetAllDisplayInfoOfGroup(sptr<DisplayInfo> info)
678 {
679     ScreenId screenGroupId = info->GetScreenGroupId();
680     std::map<DisplayId, sptr<DisplayInfo>> displayInfoMap;
681     std::lock_guard<std::recursive_mutex> lock(mutex_);
682     for (const auto& iter : abstractDisplayMap_) {
683         sptr<AbstractDisplay> display = iter.second;
684         if (display->GetAbstractScreenGroupId() == screenGroupId) {
685             displayInfoMap.insert(std::make_pair(display->GetId(), display->ConvertToDisplayInfo()));
686         }
687     }
688     return displayInfoMap;
689 }
690 
SetDisplayStateChangeListener(sptr<AbstractDisplay> abstractDisplay,DisplayStateChangeType type)691 void AbstractDisplayController::SetDisplayStateChangeListener(
692     sptr<AbstractDisplay> abstractDisplay, DisplayStateChangeType type)
693 {
694     ScreenId defaultDisplayId = GetDefaultDisplayId();
695     std::map<DisplayId, sptr<DisplayInfo>> displayInfoMap = GetAllDisplayInfoOfGroup(
696         abstractDisplay->ConvertToDisplayInfo());
697     displayStateChangeListener_(defaultDisplayId, abstractDisplay->ConvertToDisplayInfo(), displayInfoMap, type);
698 }
699 
GetDefaultDisplayId()700 DisplayId AbstractDisplayController::GetDefaultDisplayId()
701 {
702     DisplayId defaultDisplayId = DISPLAY_ID_INVALID;
703     ScreenId defaultScreenId = abstractScreenController_->GetDefaultAbstractScreenId();
704     sptr<AbstractDisplay> defaultDisplay = GetAbstractDisplayByScreen(defaultScreenId);
705     if (defaultDisplay != nullptr) {
706         defaultDisplayId = defaultDisplay->GetId();
707     }
708     return defaultDisplayId;
709 }
710 } // namespace OHOS::Rosen