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_screen_controller.h" 17 18#include <sstream> 19 20#include <cinttypes> 21#include <hitrace_meter.h> 22#include <parameters.h> 23#include <screen_manager/rs_screen_mode_info.h> 24#include <screen_manager/screen_types.h> 25#include <surface.h> 26#include <thread> 27 28#include "sys_cap_util.h" 29#include "display_manager_agent_controller.h" 30#include "display_manager_service.h" 31#include "event_runner.h" 32#include "screen_rotation_controller.h" 33#include "window_manager_hilog.h" 34 35#ifdef SOC_PERF_ENABLE 36#include "socperf_client.h" 37#endif 38 39namespace OHOS::Rosen { 40namespace { 41constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "AbstractScreenController"}; 42const std::string CONTROLLER_THREAD_ID = "AbstractScreenControllerThread"; 43const static uint32_t MAX_RETRY_NUM = 3; 44const static uint32_t RETRY_WAIT_MS = 100; 45} 46 47AbstractScreenController::AbstractScreenController(std::recursive_mutex& mutex) 48 : mutex_(mutex), rsInterface_(RSInterfaces::GetInstance()) 49{ 50 auto runner = AppExecFwk::EventRunner::Create(CONTROLLER_THREAD_ID); 51 controllerHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner); 52} 53 54AbstractScreenController::~AbstractScreenController() = default; 55 56void AbstractScreenController::Init() 57{ 58 WLOGFI("screen controller init"); 59 RegisterRsScreenConnectionChangeListener(); 60} 61 62void AbstractScreenController::RegisterRsScreenConnectionChangeListener() 63{ 64 WLOGFI("RegisterRsScreenConnectionChangeListener"); 65 auto res = rsInterface_.SetScreenChangeCallback( 66 [this](ScreenId rsScreenId, ScreenEvent screenEvent) { OnRsScreenConnectionChange(rsScreenId, screenEvent); }); 67 if (res != StatusCode::SUCCESS) { 68 auto task = [this] { 69 RegisterRsScreenConnectionChangeListener(); 70 }; 71 // post task after 50 ms. 72 controllerHandler_->PostTask(task, "wms:RegisterRsScreenConnectionChangeListener", 73 50, AppExecFwk::EventQueue::Priority::HIGH); 74 } 75} 76 77std::vector<ScreenId> AbstractScreenController::GetAllScreenIds() const 78{ 79 std::lock_guard<std::recursive_mutex> lock(mutex_); 80 std::vector<ScreenId> res; 81 for (const auto& iter : dmsScreenMap_) { 82 res.emplace_back(iter.first); 83 } 84 return res; 85} 86 87std::vector<ScreenId> AbstractScreenController::GetAllValidScreenIds(const std::vector<ScreenId>& screenIds) const 88{ 89 std::lock_guard<std::recursive_mutex> lock(mutex_); 90 std::vector<ScreenId> validScreenIds; 91 for (ScreenId screenId : screenIds) { 92 auto screenIdIter = std::find(validScreenIds.begin(), validScreenIds.end(), screenId); 93 if (screenIdIter != validScreenIds.end()) { 94 continue; 95 } 96 auto iter = dmsScreenMap_.find(screenId); 97 if (iter != dmsScreenMap_.end() && iter->second->type_ != ScreenType::UNDEFINED) { 98 validScreenIds.emplace_back(screenId); 99 } 100 } 101 return validScreenIds; 102} 103 104const std::shared_ptr<RSDisplayNode>& AbstractScreenController::GetRSDisplayNodeByScreenId(ScreenId dmsScreenId) const 105{ 106 static std::shared_ptr<RSDisplayNode> notFound = nullptr; 107 sptr<AbstractScreen> screen = GetAbstractScreen(dmsScreenId); 108 if (screen == nullptr) { 109 WLOGFE("screen is nullptr"); 110 return notFound; 111 } 112 if (screen->rsDisplayNode_ == nullptr) { 113 WLOGE("rsDisplayNode_ is nullptr"); 114 return notFound; 115 } 116 WLOGI("GetRSDisplayNodeByScreenId: screen: %{public}" PRIu64", nodeId: %{public}" PRIu64" ", 117 screen->dmsId_, screen->rsDisplayNode_->GetId()); 118 return screen->rsDisplayNode_; 119} 120 121void AbstractScreenController::UpdateRSTree(ScreenId dmsScreenId, ScreenId parentScreenId, 122 std::shared_ptr<RSSurfaceNode>& surfaceNode, bool isAdd, bool isMultiDisplay) 123{ 124 sptr<AbstractScreen> abstractScreen = GetAbstractScreen(dmsScreenId); 125 if (abstractScreen == nullptr) { 126 WLOGE("[UpdateRSTree] can not find abstractScreen"); 127 return; 128 } 129 if (isMultiDisplay) { 130 sptr<AbstractScreen> parentAbstractScreen = GetAbstractScreen(parentScreenId); 131 if (parentAbstractScreen == nullptr) { 132 WLOGE("[UpdateRSTree] can not find parentAbstractScreen"); 133 return; 134 } 135 if (parentAbstractScreen->rsDisplayNode_ == nullptr) { 136 WLOGE("rsDisplayNode of parentAbstractScreen is nullptr"); 137 return; 138 } 139 abstractScreen->UpdateDisplayGroupRSTree(surfaceNode, parentAbstractScreen->rsDisplayNode_->GetId(), isAdd); 140 } else { 141 abstractScreen->UpdateRSTree(surfaceNode, isAdd); 142 } 143} 144 145DMError AbstractScreenController::AddSurfaceNodeToScreen(ScreenId dmsScreenId, 146 std::shared_ptr<RSSurfaceNode>& surfaceNode, bool onTop) 147{ 148 sptr<AbstractScreen> abstractScreen = GetAbstractScreen(dmsScreenId); 149 if (abstractScreen == nullptr) { 150 WLOGFE("Can not find abstractScreen"); 151 return DMError::DM_ERROR_NULLPTR; 152 } 153 return abstractScreen->AddSurfaceNode(surfaceNode, onTop); 154} 155 156DMError AbstractScreenController::RemoveSurfaceNodeFromScreen(ScreenId dmsScreenId, 157 std::shared_ptr<RSSurfaceNode>& surfaceNode) 158{ 159 sptr<AbstractScreen> abstractScreen = GetAbstractScreen(dmsScreenId); 160 if (abstractScreen == nullptr) { 161 WLOGFE("Can not find abstractScreen"); 162 return DMError::DM_ERROR_NULLPTR; 163 } 164 return abstractScreen->RemoveSurfaceNode(surfaceNode); 165} 166 167sptr<AbstractScreen> AbstractScreenController::GetAbstractScreen(ScreenId dmsScreenId) const 168{ 169 WLOGD("GetAbstractScreen: screenId: %{public}" PRIu64"", dmsScreenId); 170 std::lock_guard<std::recursive_mutex> lock(mutex_); 171 auto iter = dmsScreenMap_.find(dmsScreenId); 172 if (iter == dmsScreenMap_.end()) { 173 WLOGE("did not find screen:%{public}" PRIu64"", dmsScreenId); 174 return nullptr; 175 } 176 return iter->second; 177} 178 179sptr<AbstractScreenGroup> AbstractScreenController::GetAbstractScreenGroup(ScreenId dmsScreenId) 180{ 181 std::lock_guard<std::recursive_mutex> lock(mutex_); 182 auto iter = dmsScreenGroupMap_.find(dmsScreenId); 183 if (iter == dmsScreenGroupMap_.end()) { 184 WLOGE("did not find screen:%{public}" PRIu64"", dmsScreenId); 185 return nullptr; 186 } 187 return iter->second; 188} 189 190ScreenId AbstractScreenController::GetDefaultAbstractScreenId() 191{ 192 if (defaultRsScreenId_ == SCREEN_ID_INVALID) { 193 defaultRsScreenId_ = rsInterface_.GetDefaultScreenId(); 194 } 195 if (defaultRsScreenId_ == SCREEN_ID_INVALID) { 196 WLOGFW("GetDefaultAbstractScreenId, rsDefaultId is invalid."); 197 return SCREEN_ID_INVALID; 198 } 199 std::lock_guard<std::recursive_mutex> lock(mutex_); 200 ScreenId defaultDmsScreenId; 201 if (screenIdManager_.ConvertToDmsScreenId(defaultRsScreenId_, defaultDmsScreenId)) { 202 WLOGFD("GetDefaultAbstractScreenId, screen:%{public}" PRIu64"", defaultDmsScreenId); 203 return defaultDmsScreenId; 204 } 205 WLOGFI("GetDefaultAbstractScreenId, default screen is null, try to get."); 206 ProcessScreenConnected(defaultRsScreenId_); 207 return screenIdManager_.ConvertToDmsScreenId(defaultRsScreenId_); 208} 209 210ScreenId AbstractScreenController::ConvertToRsScreenId(ScreenId dmsScreenId) const 211{ 212 std::lock_guard<std::recursive_mutex> lock(mutex_); 213 return screenIdManager_.ConvertToRsScreenId(dmsScreenId); 214} 215 216ScreenId AbstractScreenController::ConvertToDmsScreenId(ScreenId rsScreenId) const 217{ 218 std::lock_guard<std::recursive_mutex> lock(mutex_); 219 return screenIdManager_.ConvertToDmsScreenId(rsScreenId); 220} 221 222void AbstractScreenController::RegisterAbstractScreenCallback(sptr<AbstractScreenCallback> cb) 223{ 224 std::lock_guard<std::recursive_mutex> lock(mutex_); 225 abstractScreenCallback_ = cb; 226 if (abstractScreenCallback_ == nullptr) { 227 return; 228 } 229 for (auto& iter : dmsScreenMap_) { 230 if (iter.second != nullptr) { 231 WLOGFI("dmsScreenId :%{public}" PRIu64"", iter.first); 232 abstractScreenCallback_->onConnect_(iter.second); 233 } 234 } 235} 236 237void AbstractScreenController::OnRsScreenConnectionChange(ScreenId rsScreenId, ScreenEvent screenEvent) 238{ 239 WLOGFI("RS screen event. rsScreenId:%{public}" PRIu64", defaultRsScreenId_:%{public}" PRIu64", event:%{public}u", 240 rsScreenId, static_cast<uint64_t>(defaultRsScreenId_), static_cast<uint32_t>(screenEvent)); 241 if (screenEvent == ScreenEvent::CONNECTED) { 242 auto task = [this, rsScreenId] { 243 ProcessScreenConnected(rsScreenId); 244 }; 245 controllerHandler_->PostTask(task, "wms:OnRsScreenConnectionChange", 0, AppExecFwk::EventQueue::Priority::HIGH); 246 } else if (screenEvent == ScreenEvent::DISCONNECTED) { 247 auto task = [this, rsScreenId] { 248 ProcessScreenDisconnected(rsScreenId); 249 }; 250 controllerHandler_->PostTask(task, "wms:OnRsScreenConnectionChange", 0, AppExecFwk::EventQueue::Priority::HIGH); 251 } else { 252 WLOGE("unknown message:%{public}ud", static_cast<uint8_t>(screenEvent)); 253 } 254} 255 256void AbstractScreenController::ProcessDefaultScreenReconnected(ScreenId rsScreenId) 257{ 258 std::lock_guard<std::recursive_mutex> lock(mutex_); 259 if (rsScreenId != defaultRsScreenId_ || defaultRsScreenId_ == SCREEN_ID_INVALID) { 260 return; 261 } 262 ScreenId dmsScreenId; 263 if (!screenIdManager_.ConvertToDmsScreenId(rsScreenId, dmsScreenId)) { 264 WLOGFE("disconnect screen, rsScreenId=%{public}" PRIu64" is not in rs2DmsScreenIdMap_", rsScreenId); 265 return; 266 } 267 WLOGFD("rsScreenId=%{public}" PRIu64", dmsScreenId=%{public}" PRIu64", " 268 "defaultRsScreenId: %{public}" PRIu64"", rsScreenId, dmsScreenId, static_cast<uint64_t>(defaultRsScreenId_)); 269 auto dmsScreenMapIter = dmsScreenMap_.find(dmsScreenId); 270 if (dmsScreenMapIter != dmsScreenMap_.end()) { 271 auto screen = dmsScreenMapIter->second; 272 if (screen == nullptr) { 273 WLOGFE("screen is nullptr"); 274 return; 275 } 276 auto groupDmsId = screen->lastGroupDmsId_; 277 auto iter = dmsScreenGroupMap_.find(groupDmsId); 278 if (iter == dmsScreenGroupMap_.end()) { 279 WLOGFE("groupDmsId: %{public}" PRIu64"is not in dmsScreenGroupMap_.", groupDmsId); 280 return; 281 } 282 sptr<AbstractScreenGroup> screenGroup = iter->second; 283 if (screenGroup == nullptr) { 284 WLOGFE("screenGroup is nullptr"); 285 return; 286 } 287 Point point; 288 if (!screenGroup->AddChild(screen, point)) { 289 WLOGE("fail to add screen to group. screen: %{public}" PRIu64"", screen->dmsId_); 290 return; 291 } 292 293 // Recover default screen, set power state again 294 SetScreenPowerForAll(powerState_, PowerStateChangeReason::POWER_BUTTON, false); 295 const uint32_t level = 165; 296 RSInterfaces::GetInstance().SetScreenBacklight(rsScreenId, level); 297 } else { 298 WLOGFE("can't find screen in dmsScreenMap, dmsScreenId: %{public}" PRIu64"", dmsScreenId); 299 } 300} 301 302void AbstractScreenController::ProcessScreenConnected(ScreenId rsScreenId) 303{ 304 WLOGFI("start"); 305 std::lock_guard<std::recursive_mutex> lock(mutex_); 306 if (screenIdManager_.HasRsScreenId(rsScreenId)) { 307 WLOGFD("reconnect screen, screenId=%{public}" PRIu64"", rsScreenId); 308 ProcessDefaultScreenReconnected(rsScreenId); 309 return; 310 } 311 auto absScreen = InitAndGetScreen(rsScreenId); 312 if (absScreen == nullptr) { 313 return; 314 } 315 sptr<AbstractScreenGroup> screenGroup = AddToGroupLocked(absScreen); 316 if (screenGroup == nullptr) { 317 return; 318 } 319 if (rsScreenId == rsInterface_.GetDefaultScreenId() && absScreen->rsDisplayNode_ != nullptr) { 320 absScreen->screenRequestedOrientation_ = buildInDefaultOrientation_; 321 Rotation rotationAfter = absScreen->CalcRotation(absScreen->screenRequestedOrientation_); 322 WLOGFD("set default rotation to %{public}d for buildin screen", rotationAfter); 323 sptr<SupportedScreenModes> abstractScreenModes = absScreen->GetActiveScreenMode(); 324 if (abstractScreenModes != nullptr) { 325 float w = abstractScreenModes->width_; 326 float h = abstractScreenModes->height_; 327 float x = 0; 328 float y = 0; 329 if (!IsVertical(rotationAfter)) { 330 std::swap(w, h); 331 x = (h - w) / 2; // 2: used to calculate offset to center display node 332 y = (w - h) / 2; // 2: used to calculate offset to center display node 333 } 334 // 90.f is base degree 335 absScreen->rsDisplayNode_->SetRotation(-90.0f * static_cast<uint32_t>(rotationAfter)); 336 absScreen->rsDisplayNode_->SetFrame(x, y, w, h); 337 absScreen->rsDisplayNode_->SetBounds(x, y, w, h); 338 auto transactionProxy = RSTransactionProxy::GetInstance(); 339 if (transactionProxy != nullptr) { 340 transactionProxy->FlushImplicitTransaction(); 341 } 342 absScreen->rotation_ = rotationAfter; 343 absScreen->SetOrientation(absScreen->screenRequestedOrientation_); 344 } 345 } 346 NotifyScreenConnected(absScreen->ConvertToScreenInfo()); 347 NotifyScreenGroupChanged(absScreen->ConvertToScreenInfo(), ScreenGroupChangeEvent::ADD_TO_GROUP); 348 if (abstractScreenCallback_ != nullptr) { 349 abstractScreenCallback_->onConnect_(absScreen); 350 } 351} 352 353sptr<AbstractScreen> AbstractScreenController::InitAndGetScreen(ScreenId rsScreenId) 354{ 355 ScreenId dmsScreenId = screenIdManager_.CreateAndGetNewScreenId(rsScreenId); 356 RSScreenCapability screenCapability = rsInterface_.GetScreenCapability(rsScreenId); 357 WLOGFI("Screen name is %{public}s, phyWidth is %{public}u, phyHeight is %{public}u", 358 screenCapability.GetName().c_str(), screenCapability.GetPhyWidth(), screenCapability.GetPhyHeight()); 359 360 sptr<AbstractScreen> absScreen = 361 new(std::nothrow) AbstractScreen(this, screenCapability.GetName(), dmsScreenId, rsScreenId); 362 if (absScreen == nullptr) { 363 WLOGFE("new AbstractScreen failed."); 364 screenIdManager_.DeleteScreenId(dmsScreenId); 365 return nullptr; 366 } 367 absScreen->SetPhyWidth(screenCapability.GetPhyWidth()); 368 absScreen->SetPhyHeight(screenCapability.GetPhyHeight()); 369 370 if (!InitAbstractScreenModesInfo(absScreen)) { 371 screenIdManager_.DeleteScreenId(dmsScreenId); 372 WLOGFE("InitAndGetScreen failed."); 373 return nullptr; 374 } 375 dmsScreenMap_.insert(std::make_pair(dmsScreenId, absScreen)); 376 return absScreen; 377} 378 379void AbstractScreenController::ProcessScreenDisconnected(ScreenId rsScreenId) 380{ 381 ScreenId dmsScreenId; 382 std::lock_guard<std::recursive_mutex> lock(mutex_); 383 if (!screenIdManager_.ConvertToDmsScreenId(rsScreenId, dmsScreenId)) { 384 WLOGFE("disconnect screen, rsScreenId=%{public}" PRIu64" is not in rs2DmsScreenIdMap_", rsScreenId); 385 return; 386 } 387 WLOGFI("disconnect screen, rsScreenId= %{public}" PRIu64", dmsScreenId= %{public}" PRIu64"", 388 rsScreenId, dmsScreenId); 389 auto dmsScreenMapIter = dmsScreenMap_.find(dmsScreenId); 390 sptr<AbstractScreenGroup> screenGroup; 391 if (dmsScreenMapIter != dmsScreenMap_.end()) { 392 auto screen = dmsScreenMapIter->second; 393 if (abstractScreenCallback_ != nullptr && CheckScreenInScreenGroup(screen)) { 394 if (rsScreenId == defaultRsScreenId_ && defaultRsScreenId_ != SCREEN_ID_INVALID) { 395 // Disconnect default screen 396 RemoveDefaultScreenFromGroupLocked(screen); 397 return; 398 } 399 abstractScreenCallback_->onDisconnect_(screen); 400 } 401 screenGroup = RemoveFromGroupLocked(screen); 402 if (screenGroup != nullptr) { 403 NotifyScreenGroupChanged(screen->ConvertToScreenInfo(), ScreenGroupChangeEvent::REMOVE_FROM_GROUP); 404 } 405 dmsScreenMap_.erase(dmsScreenMapIter); 406 NotifyScreenDisconnected(dmsScreenId); 407 if (screenGroup != nullptr && screenGroup->combination_ == ScreenCombination::SCREEN_MIRROR && 408 screen->dmsId_ == screenGroup->mirrorScreenId_ && screenGroup->GetChildCount() != 0) { 409 auto defaultScreenId = GetDefaultAbstractScreenId(); 410 std::vector<ScreenId> screens; 411 for (auto& screenItem : screenGroup->GetChildren()) { 412 if (screenItem->dmsId_ != defaultScreenId) { 413 screens.emplace_back(screenItem->dmsId_); 414 } 415 } 416 MakeMirror(defaultScreenId, screens); 417 } 418 } 419 screenIdManager_.DeleteScreenId(dmsScreenId); 420} 421 422bool AbstractScreenController::InitAbstractScreenModesInfo(sptr<AbstractScreen>& absScreen) 423{ 424 std::vector<RSScreenModeInfo> allModes = rsInterface_.GetScreenSupportedModes(absScreen->rsId_); 425 if (allModes.size() == 0) { 426 WLOGE("supported screen mode is 0, screenId=%{public}" PRIu64"", absScreen->rsId_); 427 return false; 428 } 429 for (const RSScreenModeInfo& rsScreenModeInfo : allModes) { 430 sptr<SupportedScreenModes> info = new(std::nothrow) SupportedScreenModes(); 431 if (info == nullptr) { 432 WLOGFE("create SupportedScreenModes failed"); 433 return false; 434 } 435 info->id_ = static_cast<uint32_t>(rsScreenModeInfo.GetScreenModeId()); 436 info->width_ = static_cast<uint32_t>(rsScreenModeInfo.GetScreenWidth()); 437 info->height_ = static_cast<uint32_t>(rsScreenModeInfo.GetScreenHeight()); 438 info->refreshRate_ = rsScreenModeInfo.GetScreenRefreshRate(); 439 absScreen->modes_.push_back(info); 440 WLOGD("fill screen idx:%{public}d w/h:%{public}d/%{public}d", 441 rsScreenModeInfo.GetScreenModeId(), info->width_, info->height_); 442 } 443 int32_t activeModeId = rsInterface_.GetScreenActiveMode(absScreen->rsId_).GetScreenModeId(); 444 WLOGD("fill screen activeModeId:%{public}d", activeModeId); 445 if (static_cast<std::size_t>(activeModeId) >= allModes.size()) { 446 WLOGE("activeModeId exceed, screenId=%{public}" PRIu64", activeModeId:%{public}d/%{public}ud", 447 absScreen->rsId_, activeModeId, static_cast<uint32_t>(allModes.size())); 448 return false; 449 } 450 absScreen->activeIdx_ = activeModeId; 451 return true; 452} 453 454sptr<AbstractScreenGroup> AbstractScreenController::AddToGroupLocked(sptr<AbstractScreen> newScreen) 455{ 456 sptr<AbstractScreenGroup> res; 457 if (dmsScreenGroupMap_.empty()) { 458 WLOGFI("connect the first screen"); 459 res = AddAsFirstScreenLocked(newScreen); 460 } else { 461 res = AddAsSuccedentScreenLocked(newScreen); 462 } 463 return res; 464} 465 466void AbstractScreenController::RemoveDefaultScreenFromGroupLocked(sptr<AbstractScreen> screen) 467{ 468 std::lock_guard<std::recursive_mutex> lock(mutex_); 469 if (screen == nullptr) { 470 return; 471 } 472 auto groupDmsId = screen->groupDmsId_; 473 auto iter = dmsScreenGroupMap_.find(groupDmsId); 474 if (iter == dmsScreenGroupMap_.end()) { 475 WLOGFE("groupDmsId:%{public}" PRIu64"is not in dmsScreenGroupMap_.", groupDmsId); 476 return; 477 } 478 sptr<AbstractScreenGroup> screenGroup = iter->second; 479 if (screenGroup == nullptr) { 480 return; 481 } 482 auto rsScreenId = screen->rsId_; 483 bool res = screenGroup->RemoveDefaultScreen(screen); 484 if (!res) { 485 WLOGFE("RemoveDefaultScreen failed, rsScreenId: %{public}" PRIu64"", rsScreenId); 486 } 487} 488 489sptr<AbstractScreenGroup> AbstractScreenController::RemoveFromGroupLocked(sptr<AbstractScreen> screen) 490{ 491 std::lock_guard<std::recursive_mutex> lock(mutex_); 492 if (screen == nullptr) { 493 return nullptr; 494 } 495 auto groupDmsId = screen->groupDmsId_; 496 auto iter = dmsScreenGroupMap_.find(groupDmsId); 497 if (iter == dmsScreenGroupMap_.end()) { 498 WLOGFE("groupDmsId:%{public}" PRIu64"is not in dmsScreenGroupMap_.", groupDmsId); 499 return nullptr; 500 } 501 sptr<AbstractScreenGroup> screenGroup = iter->second; 502 if (!RemoveChildFromGroup(screen, screenGroup)) { 503 WLOGFE("RemoveChildFromGroup failed"); 504 return nullptr; 505 } 506 return screenGroup; 507} 508 509bool AbstractScreenController::RemoveChildFromGroup(sptr<AbstractScreen> screen, sptr<AbstractScreenGroup> screenGroup) 510{ 511 bool res = screenGroup->RemoveChild(screen); 512 if (!res) { 513 WLOGFE("remove screen:%{public}" PRIu64" failed from screenGroup:%{public}" PRIu64".", 514 screen->dmsId_, screen->groupDmsId_); 515 return false; 516 } 517 if (screenGroup->GetChildCount() == 0) { 518 // Group removed, need to do something. 519 std::lock_guard<std::recursive_mutex> lock(mutex_); 520 dmsScreenGroupMap_.erase(screenGroup->dmsId_); 521 dmsScreenMap_.erase(screenGroup->dmsId_); 522 } 523 return true; 524} 525 526bool AbstractScreenController::CheckScreenInScreenGroup(sptr<AbstractScreen> screen) const 527{ 528 std::lock_guard<std::recursive_mutex> lock(mutex_); 529 auto groupDmsId = screen->groupDmsId_; 530 auto iter = dmsScreenGroupMap_.find(groupDmsId); 531 if (iter == dmsScreenGroupMap_.end()) { 532 WLOGFE("groupDmsId:%{public}" PRIu64"is not in dmsScreenGroupMap_.", groupDmsId); 533 return false; 534 } 535 sptr<AbstractScreenGroup> screenGroup = iter->second; 536 return screenGroup->HasChild(screen->dmsId_); 537} 538 539sptr<AbstractScreenGroup> AbstractScreenController::AddAsFirstScreenLocked(sptr<AbstractScreen> newScreen) 540{ 541 ScreenId dmsGroupScreenId = screenIdManager_.CreateAndGetNewScreenId(SCREEN_ID_INVALID); 542 std::ostringstream buffer; 543 buffer<<"ScreenGroup_"<<dmsGroupScreenId; 544 std::string name = buffer.str(); 545 // default ScreenCombination is mirror 546 isExpandCombination_ = system::GetParameter("persist.display.expand.enabled", "0") == "1"; 547 sptr<AbstractScreenGroup> screenGroup; 548 if (isExpandCombination_) { 549 screenGroup = new(std::nothrow) AbstractScreenGroup(this, dmsGroupScreenId, 550 SCREEN_ID_INVALID, name, ScreenCombination::SCREEN_EXPAND); 551 } else { 552 screenGroup = new(std::nothrow) AbstractScreenGroup(this, dmsGroupScreenId, 553 SCREEN_ID_INVALID, name, ScreenCombination::SCREEN_MIRROR); 554 } 555 556 if (screenGroup == nullptr) { 557 WLOGE("new AbstractScreenGroup failed"); 558 screenIdManager_.DeleteScreenId(dmsGroupScreenId); 559 return nullptr; 560 } 561 Point point; 562 if (!screenGroup->AddChild(newScreen, point)) { 563 WLOGE("fail to add screen to group. screen=%{public}" PRIu64"", newScreen->dmsId_); 564 screenIdManager_.DeleteScreenId(dmsGroupScreenId); 565 return nullptr; 566 } 567 auto iter = dmsScreenGroupMap_.find(dmsGroupScreenId); 568 if (iter != dmsScreenGroupMap_.end()) { 569 WLOGE("group screen existed. id=%{public}" PRIu64"", dmsGroupScreenId); 570 dmsScreenGroupMap_.erase(iter); 571 } 572 dmsScreenGroupMap_.insert(std::make_pair(dmsGroupScreenId, screenGroup)); 573 dmsScreenMap_.insert(std::make_pair(dmsGroupScreenId, screenGroup)); 574 screenGroup->mirrorScreenId_ = newScreen->dmsId_; 575 WLOGI("connect new group screen, screenId: %{public}" PRIu64", screenGroupId: %{public}" PRIu64", " 576 "combination:%{public}u", newScreen->dmsId_, dmsGroupScreenId, newScreen->type_); 577 return screenGroup; 578} 579 580sptr<AbstractScreenGroup> AbstractScreenController::AddAsSuccedentScreenLocked(sptr<AbstractScreen> newScreen) 581{ 582 ScreenId defaultScreenId = GetDefaultAbstractScreenId(); 583 auto iter = dmsScreenMap_.find(defaultScreenId); 584 if (iter == dmsScreenMap_.end()) { 585 WLOGE("AddAsSuccedentScreenLocked. defaultScreenId:%{public}" PRIu64" is not in dmsScreenMap_.", 586 defaultScreenId); 587 return nullptr; 588 } 589 auto screen = iter->second; 590 auto screenGroupIter = dmsScreenGroupMap_.find(screen->groupDmsId_); 591 if (screenGroupIter == dmsScreenGroupMap_.end()) { 592 WLOGE("AddAsSuccedentScreenLocked. groupDmsId:%{public}" PRIu64" is not in dmsScreenGroupMap_.", 593 screen->groupDmsId_); 594 return nullptr; 595 } 596 auto screenGroup = screenGroupIter->second; 597 Point point; 598 if (screenGroup->combination_ == ScreenCombination::SCREEN_EXPAND) { 599 for (auto& child : screenGroup->GetChildren()) { 600 WLOGD("AddAsSuccedentScreenLocked. defaultScreen rotation:%d", child->rotation_); 601 if (child->rotation_ == Rotation::ROTATION_90 || child->rotation_ == Rotation::ROTATION_270) { 602 point.posX_ += static_cast<int32_t>(child->GetActiveScreenMode()->height_); 603 } else { 604 point.posX_ += static_cast<int32_t>(child->GetActiveScreenMode()->width_); 605 } 606 } 607 WLOGD("AddAsSuccedentScreenLocked. point:[%d %d]", point.posX_, point.posY_); 608 } 609 screenGroup->AddChild(newScreen, point); 610 return screenGroup; 611} 612 613ScreenId AbstractScreenController::CreateVirtualScreen(VirtualScreenOption option, 614 const sptr<IRemoteObject>& displayManagerAgent) 615{ 616 ScreenId rsId = rsInterface_.CreateVirtualScreen(option.name_, option.width_, 617 option.height_, option.surface_, SCREEN_ID_INVALID, option.flags_); 618 WLOGFI("id: %{public}" PRIu64"", rsId); 619 if (rsId == SCREEN_ID_INVALID) { 620 return SCREEN_ID_INVALID; 621 } 622 std::lock_guard<std::recursive_mutex> lock(mutex_); 623 ScreenId dmsScreenId = SCREEN_ID_INVALID; 624 if (!screenIdManager_.ConvertToDmsScreenId(rsId, dmsScreenId)) { 625 dmsScreenId = screenIdManager_.CreateAndGetNewScreenId(rsId); 626 auto absScreen = InitVirtualScreen(dmsScreenId, rsId, option); 627 if (absScreen == nullptr) { 628 screenIdManager_.DeleteScreenId(dmsScreenId); 629 return SCREEN_ID_INVALID; 630 } 631 dmsScreenMap_.insert(std::make_pair(dmsScreenId, absScreen)); 632 NotifyScreenConnected(absScreen->ConvertToScreenInfo()); 633 if (deathRecipient_ == nullptr) { 634 deathRecipient_ = 635 new AgentDeathRecipient([this](const sptr<IRemoteObject>& agent) { OnRemoteDied(agent); }); 636 } 637 auto agIter = screenAgentMap_.find(displayManagerAgent); 638 if (agIter == screenAgentMap_.end()) { 639 displayManagerAgent->AddDeathRecipient(deathRecipient_); 640 } 641 screenAgentMap_[displayManagerAgent].emplace_back(dmsScreenId); 642 } else { 643 WLOGFI("id: %{public}" PRIu64" appears in screenIdManager_. ", rsId); 644 } 645 return dmsScreenId; 646} 647 648sptr<AbstractScreen> AbstractScreenController::InitVirtualScreen(ScreenId dmsScreenId, ScreenId rsId, 649 VirtualScreenOption option) 650{ 651 sptr<AbstractScreen> absScreen = new(std::nothrow) AbstractScreen(this, option.name_, dmsScreenId, rsId); 652 sptr<SupportedScreenModes> info = new(std::nothrow) SupportedScreenModes(); 653 if (absScreen == nullptr || info == nullptr) { 654 WLOGFI("new AbstractScreen or SupportedScreenModes failed"); 655 screenIdManager_.DeleteScreenId(dmsScreenId); 656 rsInterface_.RemoveVirtualScreen(rsId); 657 return nullptr; 658 } 659 info->width_ = option.width_; 660 info->height_ = option.height_; 661 auto defaultScreen = GetAbstractScreen(GetDefaultAbstractScreenId()); 662 if (defaultScreen != nullptr && defaultScreen->GetActiveScreenMode() != nullptr) { 663 info->refreshRate_ = defaultScreen->GetActiveScreenMode()->refreshRate_; 664 } 665 absScreen->modes_.emplace_back(info); 666 absScreen->activeIdx_ = 0; 667 absScreen->type_ = ScreenType::VIRTUAL; 668 absScreen->virtualPixelRatio_ = option.density_; 669 return absScreen; 670} 671 672DMError AbstractScreenController::DestroyVirtualScreen(ScreenId screenId) 673{ 674 WLOGFI("AbstractScreenController::DestroyVirtualScreen"); 675 std::lock_guard<std::recursive_mutex> lock(mutex_); 676 ScreenId rsScreenId = SCREEN_ID_INVALID; 677 screenIdManager_.ConvertToRsScreenId(screenId, rsScreenId); 678 679 sptr<IDisplayManagerAgent> displayManagerAgent = nullptr; 680 bool agentFound = false; 681 for (auto &agentIter : screenAgentMap_) { 682 for (auto iter = agentIter.second.begin(); iter != agentIter.second.end(); iter++) { 683 if (*iter == screenId) { 684 iter = agentIter.second.erase(iter); 685 agentFound = true; 686 break; 687 } 688 } 689 if (agentFound) { 690 if (agentIter.first != nullptr && agentIter.second.empty()) { 691 agentIter.first->RemoveDeathRecipient(deathRecipient_); 692 screenAgentMap_.erase(agentIter.first); 693 } 694 break; 695 } 696 } 697 698 if (rsScreenId != SCREEN_ID_INVALID && GetAbstractScreen(screenId) != nullptr) { 699 ProcessScreenDisconnected(rsScreenId); 700 } 701 screenIdManager_.DeleteScreenId(screenId); 702 703 if (rsScreenId == SCREEN_ID_INVALID) { 704 WLOGFE("DestroyVirtualScreen: No corresponding rsScreenId"); 705 return DMError::DM_ERROR_INVALID_PARAM; 706 } 707 rsInterface_.RemoveVirtualScreen(rsScreenId); 708 return DMError::DM_OK; 709} 710 711DMError AbstractScreenController::SetVirtualScreenSurface(ScreenId screenId, sptr<Surface> surface) 712{ 713 WLOGFI("begin"); 714 std::lock_guard<std::recursive_mutex> lock(mutex_); 715 int32_t res = -1; 716 ScreenId rsScreenId; 717 if (screenIdManager_.ConvertToRsScreenId(screenId, rsScreenId)) { 718 res = rsInterface_.SetVirtualScreenSurface(rsScreenId, surface); 719 } 720 if (res != 0) { 721 WLOGE("SetVirtualScreenSurface failed in RenderService"); 722 return DMError::DM_ERROR_RENDER_SERVICE_FAILED; 723 } 724 return DMError::DM_OK; 725} 726 727void AbstractScreenController::SetBuildInDefaultOrientation(Orientation orientation) 728{ 729 if (orientation >= Orientation::BEGIN && orientation <= Orientation::END) { 730 buildInDefaultOrientation_ = orientation; 731 } 732} 733 734DMError AbstractScreenController::SetOrientation(ScreenId screenId, Orientation newOrientation, 735 bool isFromWindow, bool withAnimation) 736{ 737 WLOGD("set orientation. screen %{public}" PRIu64" orientation %{public}u", screenId, newOrientation); 738 auto screen = GetAbstractScreen(screenId); 739 if (screen == nullptr) { 740 WLOGFE("fail to set orientation, cannot find screen %{public}" PRIu64"", screenId); 741 return DMError::DM_ERROR_NULLPTR; 742 } 743 if (screen->isScreenGroup_) { 744 WLOGE("cannot set orientation to the combination. screen: %{public}" PRIu64"", screenId); 745 return DMError::DM_ERROR_NULLPTR; 746 } 747 if (isFromWindow) { 748 if (newOrientation == Orientation::UNSPECIFIED) { 749 newOrientation = screen->screenRequestedOrientation_; 750 withAnimation = true; 751 } 752 } else { 753 screen->screenRequestedOrientation_ = newOrientation; 754 } 755 if (screen->orientation_ == newOrientation) { 756 WLOGFD("skip setting orientation. screen %{public}" PRIu64" orientation %{public}u", screenId, newOrientation); 757 return DMError::DM_OK; 758 } 759 if (isFromWindow) { 760 ScreenRotationController::ProcessOrientationSwitch(newOrientation, withAnimation); 761 } else { 762 Rotation rotationAfter = screen->CalcRotation(newOrientation); 763 SetRotation(screenId, rotationAfter, false); 764 screen->rotation_ = rotationAfter; 765 } 766 if (!screen->SetOrientation(newOrientation)) { 767 WLOGE("fail to set rotation, screen %{public}" PRIu64"", screenId); 768 return DMError::DM_ERROR_NULLPTR; 769 } 770 771 // Notify rotation event to ScreenManager 772 NotifyScreenChanged(screen->ConvertToScreenInfo(), ScreenChangeEvent::UPDATE_ORIENTATION); 773 // Notify rotation event to AbstractDisplayController 774 if (abstractScreenCallback_ != nullptr) { 775 if (!withAnimation) { 776 abstractScreenCallback_->onChange_(screen, DisplayChangeEvent::UPDATE_ORIENTATION_FROM_WINDOW); 777 } else { 778 abstractScreenCallback_->onChange_(screen, DisplayChangeEvent::UPDATE_ORIENTATION); 779 } 780 } 781 782 auto screenGroup = screen->GetGroup(); 783 if (screenGroup) { 784 UpdateScreenGroupLayout(screenGroup); 785 } 786 787 return DMError::DM_OK; 788} 789 790void AbstractScreenController::UpdateScreenGroupLayout(sptr<AbstractScreenGroup> screenGroup) 791{ 792 if (screenGroup->combination_ != ScreenCombination::SCREEN_EXPAND) { 793 return; 794 } 795 796 auto screens = screenGroup->GetChildren(); 797 if (screens.size() <= 1) { 798 return; 799 } 800 801 // update display node's start point from left to right. 802 std::sort(screens.begin(), screens.end(), [](const auto &a, const auto &b) { 803 return a->startPoint_.posX_ < b->startPoint_.posX_; 804 }); 805 806 Point point; 807 uint32_t width = 0; 808 for (auto& screen : screens) { 809 auto mode = screen->GetActiveScreenMode(); 810 if (!mode) { 811 WLOGE("no active screen mode"); 812 continue; 813 } 814 815 if (screen->startPoint_.posX_ != point.posX_) { 816 screen->UpdateRSDisplayNode(point); 817 if (abstractScreenCallback_ != nullptr) { 818 abstractScreenCallback_->onChange_(screen, DisplayChangeEvent::DISPLAY_SIZE_CHANGED); 819 } 820 } 821 822 if (screen->rotation_ == Rotation::ROTATION_90 || 823 screen->rotation_ == Rotation::ROTATION_270) { 824 width = mode->height_; 825 } else { 826 width = mode->width_; 827 } 828 829 point.posX_ += static_cast<int32_t>(width); 830 } 831} 832 833void AbstractScreenController::SetScreenRotateAnimation( 834 sptr<AbstractScreen>& screen, ScreenId screenId, Rotation rotationAfter, bool withAnimation) 835{ 836 sptr<SupportedScreenModes> abstractScreenModes = screen->GetActiveScreenMode(); 837 struct ScreenRect srect = {0, 0, 0, 0}; 838 if (abstractScreenModes != nullptr) { 839 srect.h = abstractScreenModes->height_; 840 srect.w = abstractScreenModes->width_; 841 } 842 if (!IsVertical(rotationAfter)) { 843 std::swap(srect.w, srect.h); 844 srect.x = (srect.h - srect.w) / 2; // 2: used to calculate offset to center display node 845 srect.y = (srect.w - srect.h) / 2; // 2: used to calculate offset to center display node 846 } 847 const std::shared_ptr<RSDisplayNode>& displayNode = GetRSDisplayNodeByScreenId(screenId); 848 if (displayNode == nullptr) { 849 return; 850 } 851 if (rotationAfter == Rotation::ROTATION_0 && screen->rotation_ == Rotation::ROTATION_270) { 852 WLOGFD("[FixOrientation] display rotate with animation"); 853 // avoid animation 270, 240, 210 ... 30, 0, should play from 90->0 854 displayNode->SetRotation(90.f); 855 } else if (rotationAfter == Rotation::ROTATION_270 && screen->rotation_ == Rotation::ROTATION_0) { 856 WLOGFD("[FixOrientation] display rotate with animation"); 857 // avoid animation 0, 30, 60 ... 270, should play from 360->270 858 displayNode->SetRotation(-360.f); 859 } 860 if (withAnimation) { 861 WLOGFD("[FixOrientation] display rotate with animation %{public}u", rotationAfter); 862 std::weak_ptr<RSDisplayNode> weakNode = GetRSDisplayNodeByScreenId(screenId); 863 static const RSAnimationTimingProtocol timingProtocol(600); // animation time 864 // animation curve: cubic [0.2, 0.0, 0.2, 1.0] 865 static const RSAnimationTimingCurve curve = RSAnimationTimingCurve::CreateCubicCurve(0.2, 0.0, 0.2, 1.0); 866#ifdef SOC_PERF_ENABLE 867 // Increase frequency to improve windowRotation perf 868 // 10027 means "gesture" level that setting duration: 800, lit_cpu_min_freq: 1421000, mid_cpu_min_feq: 1882000 869 OHOS::SOCPERF::SocPerfClient::GetInstance().PerfRequest(10027, ""); 870#endif 871 RSNode::Animate(timingProtocol, curve, [weakNode, srect, rotationAfter, this]() { 872 auto displayNode = weakNode.lock(); 873 if (displayNode == nullptr) { 874 WLOGFE("error, cannot get DisplayNode"); 875 return; 876 } 877 SetDisplayNode(rotationAfter, displayNode, srect); 878 }, []() { 879#ifdef SOC_PERF_ENABLE 880 // ClosePerf in finishCallBack 881 OHOS::SOCPERF::SocPerfClient::GetInstance().PerfRequestEx(10027, false, ""); 882#endif 883 }); 884 } else { 885 WLOGFD("[FixOrientation] display rotate without animation %{public}u", rotationAfter); 886 SetDisplayNode(rotationAfter, displayNode, srect); 887 } 888} 889 890void AbstractScreenController::SetDisplayNode(Rotation rotationAfter, 891 const std::shared_ptr<RSDisplayNode>& displayNode, struct ScreenRect srect) 892{ 893 displayNode->SetRotation(-90.f * static_cast<uint32_t>(rotationAfter)); // 90.f is base degree 894 displayNode->SetFrame(srect.x, srect.y, srect.w, srect.h); 895 displayNode->SetBounds(srect.x, srect.y, srect.w, srect.h); 896} 897 898void AbstractScreenController::OpenRotationSyncTransaction() 899{ 900 // Before open transaction, it must flush first. 901 auto transactionProxy = RSTransactionProxy::GetInstance(); 902 if (!transactionProxy) { 903 return; 904 } 905 transactionProxy->FlushImplicitTransaction(); 906 auto syncTransactionController = RSSyncTransactionController::GetInstance(); 907 if (syncTransactionController) { 908 syncTransactionController->OpenSyncTransaction(); 909 } 910} 911 912void AbstractScreenController::CloseRotationSyncTransaction() 913{ 914 auto syncTransactionController = RSSyncTransactionController::GetInstance(); 915 if (syncTransactionController) { 916 syncTransactionController->CloseSyncTransaction(); 917 } 918} 919 920bool AbstractScreenController::SetRotation(ScreenId screenId, Rotation rotationAfter, 921 bool isFromWindow, bool withAnimation) 922{ 923 WLOGFI("Enter SetRotation, screenId: %{public}" PRIu64 ", rotation: %{public}u, isFromWindow: %{public}u," 924 "animation: %{public}u", screenId, rotationAfter, isFromWindow, withAnimation); 925 auto screen = GetAbstractScreen(screenId); 926 if (screen == nullptr) { 927 WLOGFE("SetRotation error, cannot get screen with screenId: %{public}" PRIu64, screenId); 928 return false; 929 } 930 if (rotationAfter == screen->rotation_) { 931 WLOGFD("rotation not changed. screen %{public}" PRIu64" rotation %{public}u", screenId, rotationAfter); 932 return false; 933 } 934 WLOGFD("set orientation. rotation %{public}u", rotationAfter); 935 OpenRotationSyncTransaction(); 936 SetScreenRotateAnimation(screen, screenId, rotationAfter, withAnimation); 937 screen->rotation_ = rotationAfter; 938 CloseRotationSyncTransaction(); 939 940 NotifyScreenChanged(screen->ConvertToScreenInfo(), ScreenChangeEvent::UPDATE_ROTATION); 941 // Notify rotation event to AbstractDisplayController 942 if (abstractScreenCallback_ != nullptr) { 943 if (!withAnimation) { 944 abstractScreenCallback_->onChange_(screen, DisplayChangeEvent::UPDATE_ROTATION_FROM_WINDOW); 945 } else { 946 abstractScreenCallback_->onChange_(screen, DisplayChangeEvent::UPDATE_ROTATION); 947 } 948 } 949 return true; 950} 951 952DMError AbstractScreenController::GetScreenSupportedColorGamuts(ScreenId screenId, 953 std::vector<ScreenColorGamut>& colorGamuts) 954{ 955 sptr<AbstractScreen> screen = GetAbstractScreen(screenId); 956 if (screen == nullptr) { 957 return DMError::DM_ERROR_INVALID_PARAM; 958 } 959 return screen->GetScreenSupportedColorGamuts(colorGamuts); 960} 961 962DMError AbstractScreenController::GetScreenColorGamut(ScreenId screenId, ScreenColorGamut& colorGamut) 963{ 964 sptr<AbstractScreen> screen = GetAbstractScreen(screenId); 965 if (screen == nullptr) { 966 return DMError::DM_ERROR_INVALID_PARAM; 967 } 968 return screen->GetScreenColorGamut(colorGamut); 969} 970 971DMError AbstractScreenController::SetScreenColorGamut(ScreenId screenId, int32_t colorGamutIdx) 972{ 973 sptr<AbstractScreen> screen = GetAbstractScreen(screenId); 974 if (screen == nullptr) { 975 return DMError::DM_ERROR_INVALID_PARAM; 976 } 977 return screen->SetScreenColorGamut(colorGamutIdx); 978} 979 980DMError AbstractScreenController::GetScreenGamutMap(ScreenId screenId, ScreenGamutMap& gamutMap) 981{ 982 sptr<AbstractScreen> screen = GetAbstractScreen(screenId); 983 if (screen == nullptr) { 984 return DMError::DM_ERROR_INVALID_PARAM; 985 } 986 return screen->GetScreenGamutMap(gamutMap); 987} 988 989DMError AbstractScreenController::SetScreenGamutMap(ScreenId screenId, ScreenGamutMap gamutMap) 990{ 991 sptr<AbstractScreen> screen = GetAbstractScreen(screenId); 992 if (screen == nullptr) { 993 return DMError::DM_ERROR_INVALID_PARAM; 994 } 995 return screen->SetScreenGamutMap(gamutMap); 996} 997 998DMError AbstractScreenController::SetScreenColorTransform(ScreenId screenId) 999{ 1000 sptr<AbstractScreen> screen = GetAbstractScreen(screenId); 1001 if (screen == nullptr) { 1002 return DMError::DM_ERROR_INVALID_PARAM; 1003 } 1004 return screen->SetScreenColorTransform(); 1005} 1006 1007DMError AbstractScreenController::SetScreenActiveMode(ScreenId screenId, uint32_t modeId) 1008{ 1009 WLOGI("SetScreenActiveMode: RsScreenId: %{public}" PRIu64", modeId: %{public}u", screenId, modeId); 1010 if (screenId == SCREEN_ID_INVALID) { 1011 WLOGFE("SetScreenActiveMode: invalid screenId"); 1012 return DMError::DM_ERROR_NULLPTR; 1013 } 1014 uint32_t usedModeId = 0; 1015 { 1016 std::lock_guard<std::recursive_mutex> lock(mutex_); 1017 auto screen = GetAbstractScreen(screenId); 1018 if (screen == nullptr) { 1019 WLOGFE("SetScreenActiveMode: Get AbstractScreen failed"); 1020 return DMError::DM_ERROR_NULLPTR; 1021 } 1022 ScreenId rsScreenId = SCREEN_ID_INVALID; 1023 if (!screenIdManager_.ConvertToRsScreenId(screenId, rsScreenId)) { 1024 WLOGFE("SetScreenActiveMode: No corresponding rsId"); 1025 return DMError::DM_ERROR_NULLPTR; 1026 } 1027 rsInterface_.SetScreenActiveMode(rsScreenId, modeId); 1028 usedModeId = static_cast<uint32_t>(screen->activeIdx_); 1029 screen->activeIdx_ = static_cast<int32_t>(modeId); 1030 } 1031 // add thread to process mode change sync event 1032 if (usedModeId != modeId) { 1033 WLOGI("SetScreenActiveMode: modeId: %{public}u -> %{public}u", usedModeId, modeId); 1034 auto func = [=]() { 1035 ProcessScreenModeChanged(screenId); 1036 return; 1037 }; 1038 controllerHandler_->PostTask(func, "wms:ProcessScreenModeChanged", 0, AppExecFwk::EventQueue::Priority::HIGH); 1039 } 1040 return DMError::DM_OK; 1041} 1042 1043void AbstractScreenController::ProcessScreenModeChanged(ScreenId dmsScreenId) 1044{ 1045 sptr<AbstractScreen> absScreen = nullptr; 1046 sptr<AbstractScreenCallback> absScreenCallback = nullptr; 1047 sptr<SupportedScreenModes> activeScreenMode = nullptr; 1048 { 1049 std::lock_guard<std::recursive_mutex> lock(mutex_); 1050 auto dmsScreenMapIter = dmsScreenMap_.find(dmsScreenId); 1051 if (dmsScreenMapIter == dmsScreenMap_.end()) { 1052 WLOGFE("dmsScreenId=%{public}" PRIu64" is not in dmsScreenMap", dmsScreenId); 1053 return; 1054 } 1055 absScreen = GetAbstractScreen(dmsScreenId); 1056 if (absScreen == nullptr) { 1057 WLOGFE("screen is nullptr. dmsScreenId=%{public}" PRIu64"", dmsScreenId); 1058 return; 1059 } 1060 activeScreenMode = absScreen->GetActiveScreenMode(); 1061 if (activeScreenMode == nullptr) { 1062 WLOGFE("active screen mode is nullptr. dmsScreenId=%{public}" PRIu64"", 1063 dmsScreenId); 1064 return; 1065 } 1066 absScreenCallback = abstractScreenCallback_; 1067 } 1068 uint32_t width = activeScreenMode->width_; 1069 uint32_t height = activeScreenMode->height_; 1070 uint32_t refreshRate = activeScreenMode->refreshRate_; 1071 HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:ProcessScreenModeChanged(%" PRIu64"),\ 1072 width*height(%u*%u), refreshRate(%u)", dmsScreenId, width, height, refreshRate); 1073 if (absScreenCallback != nullptr) { 1074 absScreenCallback->onChange_(absScreen, DisplayChangeEvent::DISPLAY_SIZE_CHANGED); 1075 } 1076 NotifyScreenChanged(absScreen->ConvertToScreenInfo(), ScreenChangeEvent::CHANGE_MODE); 1077} 1078 1079DMError AbstractScreenController::MakeMirror(ScreenId screenId, std::vector<ScreenId> screens) 1080{ 1081 WLOGI("MakeMirror, screenId:%{public}" PRIu64"", screenId); 1082 sptr<AbstractScreen> screen = GetAbstractScreen(screenId); 1083 if (screen == nullptr || screen->type_ != ScreenType::REAL) { 1084 WLOGFE("screen is nullptr, or screenType is not real."); 1085 return DMError::DM_ERROR_NULLPTR; 1086 } 1087 WLOGFD("GetAbstractScreenGroup start"); 1088 auto group = GetAbstractScreenGroup(screen->groupDmsId_); 1089 if (group == nullptr) { 1090 std::lock_guard<std::recursive_mutex> lock(mutex_); 1091 group = AddToGroupLocked(screen); 1092 if (group == nullptr) { 1093 WLOGFE("group is nullptr"); 1094 return DMError::DM_ERROR_NULLPTR; 1095 } 1096 NotifyScreenGroupChanged(screen->ConvertToScreenInfo(), ScreenGroupChangeEvent::ADD_TO_GROUP); 1097 if (group != nullptr && abstractScreenCallback_ != nullptr) { 1098 abstractScreenCallback_->onConnect_(screen); 1099 } 1100 } 1101 WLOGFD("GetAbstractScreenGroup end"); 1102 Point point; 1103 std::vector<Point> startPoints; 1104 startPoints.insert(startPoints.begin(), screens.size(), point); 1105 bool filterMirroredScreen = 1106 group->combination_ == ScreenCombination::SCREEN_MIRROR && group->mirrorScreenId_ == screen->dmsId_; 1107 group->mirrorScreenId_ = screen->dmsId_; 1108 ChangeScreenGroup(group, screens, startPoints, filterMirroredScreen, ScreenCombination::SCREEN_MIRROR); 1109 WLOGFI("MakeMirror success"); 1110 return DMError::DM_OK; 1111} 1112 1113DMError AbstractScreenController::StopScreens(const std::vector<ScreenId>& screenIds, ScreenCombination stopCombination) 1114{ 1115 std::lock_guard<std::recursive_mutex> lock(mutex_); 1116 for (ScreenId screenId : screenIds) { 1117 WLOGFI("ScreenId: %{public}" PRIu64"", screenId); 1118 auto screen = GetAbstractScreen(screenId); 1119 if (screen == nullptr) { 1120 WLOGFW("screen:%{public}" PRIu64" is nullptr", screenId); 1121 continue; 1122 } 1123 auto iter = dmsScreenGroupMap_.find(screen->groupDmsId_); 1124 if (iter == dmsScreenGroupMap_.end()) { 1125 WLOGFW("groupDmsId:%{public}" PRIu64"is not in dmsScreenGroupMap_", screen->groupDmsId_); 1126 continue; 1127 } 1128 sptr<AbstractScreenGroup> screenGroup = iter->second; 1129 if (screenGroup == nullptr) { 1130 WLOGFW("screenGroup:%{public}" PRIu64" is nullptr", screen->groupDmsId_); 1131 continue; 1132 } 1133 if (screenGroup->combination_ != stopCombination) { 1134 WLOGFW("try to stop screen in another combination"); 1135 continue; 1136 } 1137 if (screenGroup->combination_ == ScreenCombination::SCREEN_MIRROR && 1138 screen->dmsId_ == screenGroup->mirrorScreenId_) { 1139 WLOGFW("try to stop main mirror screen"); 1140 continue; 1141 } 1142 1143 if (abstractScreenCallback_ != nullptr && CheckScreenInScreenGroup(screen)) { 1144 abstractScreenCallback_->onDisconnect_(screen); 1145 } 1146 bool res = RemoveChildFromGroup(screen, screenGroup); 1147 if (res) { 1148 NotifyScreenGroupChanged(screen->ConvertToScreenInfo(), ScreenGroupChangeEvent::REMOVE_FROM_GROUP); 1149 } 1150 } 1151 return DMError::DM_OK; 1152} 1153 1154void AbstractScreenController::ChangeScreenGroup(sptr<AbstractScreenGroup> group, const std::vector<ScreenId>& screens, 1155 const std::vector<Point>& startPoints, bool filterScreen, ScreenCombination combination) 1156{ 1157 std::map<ScreenId, bool> removeChildResMap; 1158 std::vector<ScreenId> addScreens; 1159 std::vector<Point> addChildPos; 1160 std::lock_guard<std::recursive_mutex> lock(mutex_); 1161 for (uint64_t i = 0; i != screens.size(); i++) { 1162 ScreenId screenId = screens[i]; 1163 WLOGFI("ScreenId: %{public}" PRIu64"", screenId); 1164 auto screen = GetAbstractScreen(screenId); 1165 if (screen == nullptr) { 1166 WLOGFE("screen:%{public}" PRIu64" is nullptr", screenId); 1167 continue; 1168 } 1169 WLOGFI("Screen->groupDmsId_: %{public}" PRIu64"", screen->groupDmsId_); 1170 if (filterScreen && screen->groupDmsId_ == group->dmsId_ && group->HasChild(screen->dmsId_)) { 1171 continue; 1172 } 1173 if (abstractScreenCallback_ != nullptr && CheckScreenInScreenGroup(screen)) { 1174 abstractScreenCallback_->onDisconnect_(screen); 1175 } 1176 auto originGroup = RemoveFromGroupLocked(screen); 1177 addChildPos.emplace_back(startPoints[i]); 1178 removeChildResMap[screenId] = originGroup != nullptr; 1179 addScreens.emplace_back(screenId); 1180 } 1181 group->combination_ = combination; 1182 AddScreenToGroup(group, addScreens, addChildPos, removeChildResMap); 1183} 1184 1185void AbstractScreenController::AddScreenToGroup(sptr<AbstractScreenGroup> group, 1186 const std::vector<ScreenId>& addScreens, const std::vector<Point>& addChildPos, 1187 std::map<ScreenId, bool>& removeChildResMap) 1188{ 1189 std::vector<sptr<ScreenInfo>> addToGroup; 1190 std::vector<sptr<ScreenInfo>> removeFromGroup; 1191 std::vector<sptr<ScreenInfo>> changeGroup; 1192 for (uint64_t i = 0; i != addScreens.size(); i++) { 1193 ScreenId screenId = addScreens[i]; 1194 sptr<AbstractScreen> screen = GetAbstractScreen(screenId); 1195 if (screen == nullptr) { 1196 continue; 1197 } 1198 Point expandPoint = addChildPos[i]; 1199 WLOGFI("screenId: %{public}" PRIu64", Point: %{public}d, %{public}d", 1200 screen->dmsId_, expandPoint.posX_, expandPoint.posY_); 1201 bool addChildRes = group->AddChild(screen, expandPoint); 1202 if (removeChildResMap[screenId] && addChildRes) { 1203 changeGroup.emplace_back(screen->ConvertToScreenInfo()); 1204 WLOGFD("changeGroup"); 1205 } else if (removeChildResMap[screenId]) { 1206 WLOGFD("removeChild"); 1207 removeFromGroup.emplace_back(screen->ConvertToScreenInfo()); 1208 } else if (addChildRes) { 1209 WLOGFD("AddChild"); 1210 addToGroup.emplace_back(screen->ConvertToScreenInfo()); 1211 } else { 1212 WLOGFD("default, AddChild failed"); 1213 } 1214 if (abstractScreenCallback_ != nullptr) { 1215 abstractScreenCallback_->onConnect_(screen); 1216 } 1217 } 1218 1219 NotifyScreenGroupChanged(removeFromGroup, ScreenGroupChangeEvent::REMOVE_FROM_GROUP); 1220 NotifyScreenGroupChanged(changeGroup, ScreenGroupChangeEvent::CHANGE_GROUP); 1221 NotifyScreenGroupChanged(addToGroup, ScreenGroupChangeEvent::ADD_TO_GROUP); 1222} 1223 1224bool AbstractScreenController::MakeExpand(std::vector<ScreenId> screenIds, std::vector<Point> startPoints) 1225{ 1226 ScreenId defaultScreenId = GetDefaultAbstractScreenId(); 1227 WLOGI("MakeExpand, defaultScreenId:%{public}" PRIu64"", defaultScreenId); 1228 auto defaultScreen = GetAbstractScreen(defaultScreenId); 1229 if (defaultScreen == nullptr) { 1230 return false; 1231 } 1232 auto group = GetAbstractScreenGroup(defaultScreen->groupDmsId_); 1233 if (group == nullptr) { 1234 return false; 1235 } 1236 bool filterExpandScreen = group->combination_ == ScreenCombination::SCREEN_EXPAND; 1237 ChangeScreenGroup(group, screenIds, startPoints, filterExpandScreen, ScreenCombination::SCREEN_EXPAND); 1238 WLOGFI("MakeExpand success"); 1239 return true; 1240} 1241 1242void AbstractScreenController::RemoveVirtualScreenFromGroup(std::vector<ScreenId> screens) 1243{ 1244 if (screens.empty()) { 1245 return; 1246 } 1247 std::vector<sptr<ScreenInfo>> removeFromGroup; 1248 for (ScreenId screenId : screens) { 1249 auto screen = GetAbstractScreen(screenId); 1250 if (screen == nullptr || screen->type_ != ScreenType::VIRTUAL) { 1251 continue; 1252 } 1253 auto originGroup = GetAbstractScreenGroup(screen->groupDmsId_); 1254 if (originGroup == nullptr) { 1255 continue; 1256 } 1257 if (!originGroup->HasChild(screenId)) { 1258 continue; 1259 } 1260 if (abstractScreenCallback_ != nullptr && CheckScreenInScreenGroup(screen)) { 1261 abstractScreenCallback_->onDisconnect_(screen); 1262 } 1263 RemoveFromGroupLocked(screen); 1264 removeFromGroup.emplace_back(screen->ConvertToScreenInfo()); 1265 } 1266 NotifyScreenGroupChanged(removeFromGroup, ScreenGroupChangeEvent::REMOVE_FROM_GROUP); 1267} 1268 1269bool AbstractScreenController::OnRemoteDied(const sptr<IRemoteObject>& agent) 1270{ 1271 if (agent == nullptr) { 1272 return false; 1273 } 1274 std::lock_guard<std::recursive_mutex> lock(mutex_); 1275 auto agentIter = screenAgentMap_.find(agent); 1276 if (agentIter != screenAgentMap_.end()) { 1277 while (screenAgentMap_[agent].size() > 0) { 1278 auto diedId = screenAgentMap_[agent][0]; 1279 WLOGI("destroy screenId in OnRemoteDied: %{public}" PRIu64"", diedId); 1280 DMError res = DestroyVirtualScreen(diedId); 1281 if (res != DMError::DM_OK) { 1282 WLOGE("destroy failed in OnRemoteDied: %{public}" PRIu64"", diedId); 1283 } 1284 } 1285 screenAgentMap_.erase(agent); 1286 } 1287 return true; 1288} 1289 1290ScreenId AbstractScreenController::ScreenIdManager::CreateAndGetNewScreenId(ScreenId rsScreenId) 1291{ 1292 ScreenId dmsScreenId = dmsScreenCount_++; 1293 if (dms2RsScreenIdMap_.find(dmsScreenId) != dms2RsScreenIdMap_.end()) { 1294 WLOGFW("dmsScreenId: %{public}" PRIu64" exit in dms2RsScreenIdMap_, warning.", dmsScreenId); 1295 } 1296 dms2RsScreenIdMap_[dmsScreenId] = rsScreenId; 1297 if (rsScreenId == SCREEN_ID_INVALID) { 1298 return dmsScreenId; 1299 } 1300 if (rs2DmsScreenIdMap_.find(rsScreenId) != rs2DmsScreenIdMap_.end()) { 1301 WLOGFW("rsScreenId: %{public}" PRIu64" exit in rs2DmsScreenIdMap_, warning.", rsScreenId); 1302 } 1303 rs2DmsScreenIdMap_[rsScreenId] = dmsScreenId; 1304 return dmsScreenId; 1305} 1306 1307bool AbstractScreenController::ScreenIdManager::DeleteScreenId(ScreenId dmsScreenId) 1308{ 1309 auto iter = dms2RsScreenIdMap_.find(dmsScreenId); 1310 if (iter == dms2RsScreenIdMap_.end()) { 1311 return false; 1312 } 1313 ScreenId rsScreenId = iter->second; 1314 dms2RsScreenIdMap_.erase(dmsScreenId); 1315 rs2DmsScreenIdMap_.erase(rsScreenId); 1316 return true; 1317} 1318 1319bool AbstractScreenController::ScreenIdManager::HasDmsScreenId(ScreenId dmsScreenId) const 1320{ 1321 return dms2RsScreenIdMap_.find(dmsScreenId) != dms2RsScreenIdMap_.end(); 1322} 1323 1324bool AbstractScreenController::ScreenIdManager::HasRsScreenId(ScreenId dmsScreenId) const 1325{ 1326 return rs2DmsScreenIdMap_.find(dmsScreenId) != rs2DmsScreenIdMap_.end(); 1327} 1328 1329bool AbstractScreenController::ScreenIdManager::ConvertToRsScreenId(ScreenId dmsScreenId, ScreenId& rsScreenId) const 1330{ 1331 auto iter = dms2RsScreenIdMap_.find(dmsScreenId); 1332 if (iter == dms2RsScreenIdMap_.end()) { 1333 return false; 1334 } 1335 rsScreenId = iter->second; 1336 return true; 1337} 1338 1339ScreenId AbstractScreenController::ScreenIdManager::ConvertToRsScreenId(ScreenId dmsScreenId) const 1340{ 1341 ScreenId rsScreenId = SCREEN_ID_INVALID; 1342 ConvertToRsScreenId(dmsScreenId, rsScreenId); 1343 return rsScreenId; 1344} 1345 1346bool AbstractScreenController::ScreenIdManager::ConvertToDmsScreenId(ScreenId rsScreenId, ScreenId& dmsScreenId) const 1347{ 1348 auto iter = rs2DmsScreenIdMap_.find(rsScreenId); 1349 if (iter == rs2DmsScreenIdMap_.end()) { 1350 return false; 1351 } 1352 dmsScreenId = iter->second; 1353 return true; 1354} 1355 1356ScreenId AbstractScreenController::ScreenIdManager::ConvertToDmsScreenId(ScreenId rsScreenId) const 1357{ 1358 ScreenId dmsScreenId = SCREEN_ID_INVALID; 1359 ConvertToDmsScreenId(rsScreenId, dmsScreenId); 1360 return dmsScreenId; 1361} 1362 1363void AbstractScreenController::NotifyScreenConnected(sptr<ScreenInfo> screenInfo) const 1364{ 1365 if (screenInfo == nullptr) { 1366 WLOGFE("NotifyScreenConnected error, screenInfo is nullptr."); 1367 return; 1368 } 1369 auto task = [=] { 1370 WLOGFI("NotifyScreenConnected, screenId:%{public}" PRIu64"", screenInfo->GetScreenId()); 1371 DisplayManagerAgentController::GetInstance().OnScreenConnect(screenInfo); 1372 }; 1373 controllerHandler_->PostTask(task, "wms:OnScreenConnect", 0, AppExecFwk::EventQueue::Priority::HIGH); 1374} 1375 1376void AbstractScreenController::NotifyScreenDisconnected(ScreenId screenId) const 1377{ 1378 auto task = [=] { 1379 WLOGFI("NotifyScreenDisconnected, screenId:%{public}" PRIu64"", screenId); 1380 DisplayManagerAgentController::GetInstance().OnScreenDisconnect(screenId); 1381 }; 1382 controllerHandler_->PostTask(task, "wms:NotifyScreenDisconnected", 0, AppExecFwk::EventQueue::Priority::HIGH); 1383} 1384 1385void AbstractScreenController::NotifyScreenChanged(sptr<ScreenInfo> screenInfo, ScreenChangeEvent event) const 1386{ 1387 if (screenInfo == nullptr) { 1388 WLOGFE("NotifyScreenChanged error, screenInfo is nullptr."); 1389 return; 1390 } 1391 auto task = [=] { 1392 WLOGFI("NotifyScreenChanged, screenId:%{public}" PRIu64"", screenInfo->GetScreenId()); 1393 DisplayManagerAgentController::GetInstance().OnScreenChange(screenInfo, event); 1394 }; 1395 controllerHandler_->PostTask(task, "wms:OnScreenChange", 0, AppExecFwk::EventQueue::Priority::HIGH); 1396} 1397 1398void AbstractScreenController::NotifyScreenGroupChanged( 1399 const sptr<ScreenInfo>& screenInfo, ScreenGroupChangeEvent event) const 1400{ 1401 if (screenInfo == nullptr) { 1402 WLOGFE("screenInfo is nullptr."); 1403 return; 1404 } 1405 std::string trigger = SysCapUtil::GetClientName(); 1406 auto task = [=] { 1407 WLOGFI("screenId:%{public}" PRIu64", trigger:[%{public}s]", screenInfo->GetScreenId(), trigger.c_str()); 1408 DisplayManagerAgentController::GetInstance().OnScreenGroupChange(trigger, screenInfo, event); 1409 }; 1410 controllerHandler_->PostTask(task, "wms:OnScreenGroupChange", 0, AppExecFwk::EventQueue::Priority::HIGH); 1411} 1412 1413void AbstractScreenController::NotifyScreenGroupChanged( 1414 const std::vector<sptr<ScreenInfo>>& screenInfo, ScreenGroupChangeEvent event) const 1415{ 1416 if (screenInfo.empty()) { 1417 return; 1418 } 1419 std::string trigger = SysCapUtil::GetClientName(); 1420 auto task = [=] { 1421 WLOGFI("trigger:[%{public}s]", trigger.c_str()); 1422 DisplayManagerAgentController::GetInstance().OnScreenGroupChange(trigger, screenInfo, event); 1423 }; 1424 controllerHandler_->PostTask(task, "wms:NotifyScreenGroupChanged", 0, AppExecFwk::EventQueue::Priority::HIGH); 1425} 1426 1427bool AbstractScreenController::SetScreenPowerForAll(ScreenPowerState state, 1428 PowerStateChangeReason reason, bool needToNotify) 1429{ 1430 WLOGFI("state:%{public}u, reason:%{public}u", state, reason); 1431 auto screenIds = GetAllScreenIds(); 1432 if (screenIds.empty()) { 1433 WLOGFI("no screen info"); 1434 return false; 1435 } 1436 1437 ScreenPowerStatus status; 1438 switch (state) { 1439 case ScreenPowerState::POWER_ON: { 1440 status = ScreenPowerStatus::POWER_STATUS_ON; 1441 powerState_ = ScreenPowerState::POWER_ON; 1442 break; 1443 } 1444 case ScreenPowerState::POWER_OFF: { 1445 status = ScreenPowerStatus::POWER_STATUS_OFF; 1446 powerState_ = ScreenPowerState::POWER_OFF; 1447 break; 1448 } 1449 default: { 1450 WLOGFW("SetScreenPowerStatus state not support"); 1451 return false; 1452 } 1453 } 1454 1455 bool hasSetScreenPower = false; 1456 for (auto screenId : screenIds) { 1457 auto screen = GetAbstractScreen(screenId); 1458 if (screen == nullptr) { 1459 continue; 1460 } 1461 if (screen->type_ != ScreenType::REAL) { 1462 WLOGD("skip virtual screen %{public}" PRIu64"", screen->dmsId_); 1463 continue; 1464 } 1465 RSInterfaces::GetInstance().SetScreenPowerStatus(screen->rsId_, status); 1466 WLOGFI("set screen power status. rsscreen %{public}" PRIu64", status %{public}u", screen->rsId_, status); 1467 hasSetScreenPower = true; 1468 } 1469 WLOGFI("SetScreenPowerStatus end"); 1470 if (!hasSetScreenPower) { 1471 WLOGFI("no real screen"); 1472 return false; 1473 } 1474 if (needToNotify) { 1475 return DisplayManagerAgentController::GetInstance().NotifyDisplayPowerEvent( 1476 state == ScreenPowerState::POWER_ON ? DisplayPowerEvent::DISPLAY_ON : 1477 DisplayPowerEvent::DISPLAY_OFF, EventStatus::END); 1478 } 1479 return true; 1480} 1481 1482ScreenPowerState AbstractScreenController::GetScreenPower(ScreenId dmsScreenId) const 1483{ 1484 uint32_t retryTimes = 0; 1485 bool res = false; 1486 while (retryTimes < MAX_RETRY_NUM) { 1487 { 1488 std::lock_guard<std::recursive_mutex> lock(mutex_); 1489 if (dmsScreenMap_.find(dmsScreenId) != dmsScreenMap_.end()) { 1490 WLOGFI("find screen %{public}" PRIu64"", dmsScreenId); 1491 res = true; 1492 break; 1493 } 1494 } 1495 retryTimes++; 1496 WLOGFW("not find screen, retry %{public}u times", retryTimes); 1497 std::this_thread::sleep_for(std::chrono::milliseconds(RETRY_WAIT_MS)); 1498 } 1499 if (retryTimes >= MAX_RETRY_NUM || !res) { 1500 WLOGFE("cannot find screen %{public}" PRIu64"", dmsScreenId); 1501 return ScreenPowerState::INVALID_STATE; 1502 } 1503 1504 ScreenId rsId = ConvertToRsScreenId(dmsScreenId); 1505 auto state = static_cast<ScreenPowerState>(RSInterfaces::GetInstance().GetScreenPowerStatus(rsId)); 1506 WLOGFI("GetScreenPower:%{public}u, rsscreen:%{public}" PRIu64".", state, rsId); 1507 return state; 1508} 1509 1510DMError AbstractScreenController::SetVirtualPixelRatio(ScreenId screenId, float virtualPixelRatio) 1511{ 1512 WLOGD("set virtual pixel ratio. screen %{public}" PRIu64" virtualPixelRatio %{public}f", 1513 screenId, virtualPixelRatio); 1514 auto screen = GetAbstractScreen(screenId); 1515 if (screen == nullptr) { 1516 WLOGFE("fail to set virtual pixel ratio, cannot find screen %{public}" PRIu64"", screenId); 1517 return DMError::DM_ERROR_NULLPTR; 1518 } 1519 if (screen->isScreenGroup_) { 1520 WLOGE("cannot set virtual pixel ratio to the combination. screen: %{public}" PRIu64"", screenId); 1521 return DMError::DM_ERROR_NULLPTR; 1522 } 1523 if (fabs(screen->virtualPixelRatio_ - virtualPixelRatio) < 1e-6) { // less to 1e-6 mean equal 1524 WLOGE("The density is equivalent to the original value, no update operation is required, aborted."); 1525 return DMError::DM_OK; 1526 } 1527 screen->SetVirtualPixelRatio(virtualPixelRatio); 1528 // Notify rotation event to AbstractDisplayController 1529 if (abstractScreenCallback_ != nullptr) { 1530 abstractScreenCallback_->onChange_(screen, DisplayChangeEvent::DISPLAY_VIRTUAL_PIXEL_RATIO_CHANGED); 1531 } 1532 NotifyScreenChanged(screen->ConvertToScreenInfo(), ScreenChangeEvent::VIRTUAL_PIXEL_RATIO_CHANGED); 1533 return DMError::DM_OK; 1534} 1535} // namespace OHOS::Rosen 1536