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