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