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