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