• 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     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->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)) {
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)469 bool AbstractDisplayController::UpdateDisplaySize(sptr<AbstractDisplay> absDisplay, sptr<SupportedScreenModes> info)
470 {
471     if (absDisplay == nullptr || info == nullptr) {
472         WLOGFE("invalid params.");
473         return false;
474     }
475     if (info->height_ == static_cast<uint32_t>(absDisplay->GetHeight()) &&
476         info->width_ == static_cast<uint32_t>(absDisplay->GetWidth())) {
477         WLOGFI("keep display size. display:%{public}" PRIu64"", absDisplay->GetId());
478         return false;
479     }
480     absDisplay->SetHeight(info->height_);
481     absDisplay->SetWidth(info->width_);
482     WLOGFI("Reset H&W. id %{public}" PRIu64", size: %{public}d %{public}d",
483           absDisplay->GetId(), absDisplay->GetWidth(), absDisplay->GetHeight());
484     return true;
485 }
486 
ProcessVirtualPixelRatioChange(sptr<AbstractScreen> absScreen)487 void AbstractDisplayController::ProcessVirtualPixelRatioChange(sptr<AbstractScreen> absScreen)
488 {
489     sptr<AbstractDisplay> abstractDisplay = nullptr;
490     {
491         std::lock_guard<std::recursive_mutex> lock(mutex_);
492         auto iter = abstractDisplayMap_.begin();
493         for (; iter != abstractDisplayMap_.end(); iter++) {
494             abstractDisplay = iter->second;
495             if (abstractDisplay->GetAbstractScreenId() == absScreen->dmsId_) {
496                 WLOGFD("find abstract display of the screen. display %{public}" PRIu64", screen %{public}" PRIu64"",
497                     abstractDisplay->GetId(), absScreen->dmsId_);
498                 break;
499             }
500         }
501     }
502     if (abstractDisplay == nullptr) {
503         WLOGE("Failed to find abstract display of the screen.");
504         return;
505     }
506     abstractDisplay->SetVirtualPixelRatio(absScreen->virtualPixelRatio_);
507     // Notify virtual pixel ratio change event to WMS
508     SetDisplayStateChangeListener(abstractDisplay, DisplayStateChangeType::VIRTUAL_PIXEL_RATIO_CHANGE);
509     // Notify virtual pixel ratio change event to DisplayManager
510     DisplayManagerAgentController::GetInstance().OnDisplayChange(abstractDisplay->ConvertToDisplayInfo(),
511         DisplayChangeEvent::DISPLAY_VIRTUAL_PIXEL_RATIO_CHANGED);
512 }
513 
BindAloneScreenLocked(sptr<AbstractScreen> realAbsScreen)514 void AbstractDisplayController::BindAloneScreenLocked(sptr<AbstractScreen> realAbsScreen)
515 {
516     if (realAbsScreen == nullptr) {
517         WLOGE("BindAloneScreenLocked failed, realAbsScreen is nullptr");
518         return;
519     }
520     ScreenId defaultScreenId = abstractScreenController_->GetDefaultAbstractScreenId();
521     if (defaultScreenId != SCREEN_ID_INVALID) {
522         if (defaultScreenId != realAbsScreen->dmsId_) {
523             WLOGE("The first real screen should be default for Phone. %{public}" PRIu64"", realAbsScreen->dmsId_);
524             return;
525         }
526         sptr<SupportedScreenModes> info = realAbsScreen->GetActiveScreenMode();
527         if (info == nullptr) {
528             WLOGE("bind alone screen error, cannot get info.");
529             return;
530         }
531         if (dummyDisplay_ == nullptr) {
532             DisplayId displayId = displayCount_.fetch_add(1);
533             sptr<AbstractDisplay> display = new(std::nothrow) AbstractDisplay(displayId, info, realAbsScreen);
534             if (display == nullptr) {
535                 WLOGFE("create display failed");
536                 return;
537             }
538 
539             abstractDisplayMap_.insert((std::make_pair(display->GetId(), display)));
540             WLOGI("create display for new screen. screen:%{public}" PRIu64", display:%{public}" PRIu64"",
541                 realAbsScreen->dmsId_, display->GetId());
542             DisplayManagerAgentController::GetInstance().OnDisplayCreate(display->ConvertToDisplayInfo());
543             SetDisplayStateChangeListener(display, DisplayStateChangeType::CREATE);
544         } else {
545             WLOGI("bind display for new screen. screen:%{public}" PRIu64", display:%{public}" PRIu64"",
546                 realAbsScreen->dmsId_, dummyDisplay_->GetId());
547             bool updateFlag = static_cast<uint32_t>(dummyDisplay_->GetHeight()) == info->height_
548                     && static_cast<uint32_t>(dummyDisplay_->GetWidth()) == info->width_;
549             dummyDisplay_->BindAbstractScreen(abstractScreenController_->GetAbstractScreen(realAbsScreen->dmsId_));
550             if (updateFlag) {
551                 DisplayManagerAgentController::GetInstance().OnDisplayCreate(dummyDisplay_->ConvertToDisplayInfo());
552             }
553             dummyDisplay_ = nullptr;
554         }
555     } else {
556         WLOGE("The first real screen should be default screen for Phone. %{public}" PRIu64"", realAbsScreen->dmsId_);
557     }
558 }
559 
AddScreenToMirrorLocked(sptr<AbstractScreen> absScreen)560 void AbstractDisplayController::AddScreenToMirrorLocked(sptr<AbstractScreen> absScreen)
561 {
562     WLOGI("bind display to mirror. screen:%{public}" PRIu64"", absScreen->dmsId_);
563 }
564 
AddScreenToExpandLocked(sptr<AbstractScreen> absScreen)565 void AbstractDisplayController::AddScreenToExpandLocked(sptr<AbstractScreen> absScreen)
566 {
567     if (absScreen == nullptr) {
568         WLOGE("AddScreenToExpandLocked failed, absScreen is nullptr");
569         return;
570     }
571     for (auto iter = abstractDisplayMap_.begin(); iter != abstractDisplayMap_.end(); iter++) {
572         sptr<AbstractDisplay> abstractDisplay = iter->second;
573         if (abstractDisplay->GetAbstractScreenId() == absScreen->dmsId_) {
574             WLOGE("error, screenId: %{public}" PRIu64" already has corresponding display",
575                 absScreen->dmsId_);
576             return;
577         }
578     }
579     WLOGI("bind display to expand. screen:%{public}" PRIu64"", absScreen->dmsId_);
580     sptr<SupportedScreenModes> info;
581     ScreenId defaultScreenId = abstractScreenController_->GetDefaultAbstractScreenId();
582     sptr<AbstractScreen> defaultScreen = abstractScreenController_->GetAbstractScreen(defaultScreenId);
583     if (absScreen->type_ == ScreenType::VIRTUAL) {
584         WLOGI("screen type is virtual, use default screen info");
585         if (defaultScreen == nullptr) {
586             WLOGE("bind display error, cannot get defaultScreen.");
587             return;
588         }
589         info = defaultScreen->GetActiveScreenMode();
590     } else {
591         WLOGI("screen type is not virtual, get this screen info");
592         info = absScreen->GetActiveScreenMode();
593     }
594     if (info == nullptr) {
595         WLOGE("bind display error, cannot get info.");
596         return;
597     }
598     DisplayId displayId = displayCount_.fetch_add(1);
599     sptr<AbstractDisplay> display = new AbstractDisplay(displayId, info, absScreen);
600     Point point = abstractScreenController_->GetAbstractScreenGroup(absScreen->groupDmsId_)->
601         GetChildPosition(absScreen->dmsId_);
602     display->SetOffset(point.posX_, point.posY_);
603     abstractDisplayMap_.insert((std::make_pair(display->GetId(), display)));
604     WLOGI("create display for new screen. screen:%{public}" PRIu64", display:%{public}" PRIu64"",
605         absScreen->dmsId_, display->GetId());
606     DisplayManagerAgentController::GetInstance().OnDisplayCreate(display->ConvertToDisplayInfo());
607     SetDisplayStateChangeListener(display, DisplayStateChangeType::CREATE);
608 }
609 
SetFreeze(std::vector<DisplayId> displayIds,bool toFreeze)610 void AbstractDisplayController::SetFreeze(std::vector<DisplayId> displayIds, bool toFreeze)
611 {
612     HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:SetAllFreeze");
613     DisplayStateChangeType type = toFreeze ? DisplayStateChangeType::FREEZE : DisplayStateChangeType::UNFREEZE;
614     DisplayChangeEvent event
615         = toFreeze ? DisplayChangeEvent::DISPLAY_FREEZED : DisplayChangeEvent::DISPLAY_UNFREEZED;
616     for (DisplayId displayId : displayIds) {
617         sptr<AbstractDisplay> abstractDisplay;
618         HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:SetFreeze(%" PRIu64")", displayId);
619         {
620             WLOGI("setfreeze display %{public}" PRIu64"", displayId);
621             std::lock_guard<std::recursive_mutex> lock(mutex_);
622             auto iter = abstractDisplayMap_.find(displayId);
623             if (iter == abstractDisplayMap_.end()) {
624                 WLOGE("setfreeze fail, cannot get display %{public}" PRIu64"", displayId);
625                 continue;
626             }
627             abstractDisplay = iter->second;
628             FreezeFlag curFlag = abstractDisplay->GetFreezeFlag();
629             if ((toFreeze && (curFlag == FreezeFlag::FREEZING))
630                 || (!toFreeze && (curFlag == FreezeFlag::UNFREEZING))) {
631                 WLOGE("setfreeze fail, display %{public}" PRIu64" freezeflag is %{public}u",
632                     displayId, curFlag);
633                 continue;
634             }
635             FreezeFlag flag = toFreeze ? FreezeFlag::FREEZING : FreezeFlag::UNFREEZING;
636             abstractDisplay->SetFreezeFlag(flag);
637         }
638 
639         // Notify freeze event to WMS
640         SetDisplayStateChangeListener(abstractDisplay, type);
641         // Notify freeze event to DisplayManager
642         DisplayManagerAgentController::GetInstance().OnDisplayChange(abstractDisplay->ConvertToDisplayInfo(), event);
643     }
644 }
645 
GetAllDisplayInfoOfGroup(sptr<DisplayInfo> info)646 std::map<DisplayId, sptr<DisplayInfo>> AbstractDisplayController::GetAllDisplayInfoOfGroup(sptr<DisplayInfo> info)
647 {
648     ScreenId screenGroupId = info->GetScreenGroupId();
649     std::map<DisplayId, sptr<DisplayInfo>> displayInfoMap;
650     std::lock_guard<std::recursive_mutex> lock(mutex_);
651     for (const auto& iter : abstractDisplayMap_) {
652         sptr<AbstractDisplay> display = iter.second;
653         if (display->GetAbstractScreenGroupId() == screenGroupId) {
654             displayInfoMap.insert(std::make_pair(display->GetId(), display->ConvertToDisplayInfo()));
655         }
656     }
657     return displayInfoMap;
658 }
659 
SetDisplayStateChangeListener(sptr<AbstractDisplay> abstractDisplay,DisplayStateChangeType type)660 void AbstractDisplayController::SetDisplayStateChangeListener(
661     sptr<AbstractDisplay> abstractDisplay, DisplayStateChangeType type)
662 {
663     ScreenId defaultDisplayId = GetDefaultDisplayId();
664     std::map<DisplayId, sptr<DisplayInfo>> displayInfoMap = GetAllDisplayInfoOfGroup(
665         abstractDisplay->ConvertToDisplayInfo());
666     displayStateChangeListener_(defaultDisplayId, abstractDisplay->ConvertToDisplayInfo(), displayInfoMap, type);
667 }
668 
GetDefaultDisplayId()669 DisplayId AbstractDisplayController::GetDefaultDisplayId()
670 {
671     DisplayId defaultDisplayId = DISPLAY_ID_INVALID;
672     ScreenId defaultScreenId = abstractScreenController_->GetDefaultAbstractScreenId();
673     sptr<AbstractDisplay> defaultDisplay = GetAbstractDisplayByScreen(defaultScreenId);
674     if (defaultDisplay != nullptr) {
675         defaultDisplayId = defaultDisplay->GetId();
676     }
677     return defaultDisplayId;
678 }
679 } // namespace OHOS::Rosen