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