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