/* * Copyright (c) 2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "session_manager/include/screen_session_manager.h" #include #include #include #include #include #include #include #ifdef DEVICE_STATUS_ENABLE #include #endif // DEVICE_STATUS_ENABLE #include #include #include #include #include #include #include #include #include #include "dm_common.h" #include "fold_screen_state_internel.h" #include "multi_screen_manager.h" #include "pipeline/rs_node_map.h" #include "scene_board_judgement.h" #include "session_permission.h" #include "screen_scene_config.h" #include "surface_capture_future.h" #include "sys_cap_util.h" #include "permission.h" #include "window_manager_hilog.h" #include "screen_rotation_property.h" #include "screen_sensor_connector.h" #include "screen_setting_helper.h" #include "screen_session_dumper.h" #include "mock_session_manager_service.h" #include "connection/screen_snapshot_picker_connection.h" #include "connection/screen_cast_connection.h" #include "publish/screen_session_publish.h" #include "dms_xcollie.h" namespace OHOS::Rosen { namespace { const std::string SCREEN_SESSION_MANAGER_THREAD = "OS_ScreenSessionManager"; const std::string SCREEN_SESSION_MANAGER_SCREEN_POWER_THREAD = "OS_ScreenSessionManager_ScreenPower"; const std::string SCREEN_CAPTURE_PERMISSION = "ohos.permission.CAPTURE_SCREEN"; const std::string CUSTOM_SCREEN_CAPTURE_PERMISSION = "ohos.permission.CUSTOM_SCREEN_CAPTURE"; const std::string BOOTEVENT_BOOT_COMPLETED = "bootevent.boot.completed"; const int32_t CV_WAIT_SCREENON_MS = 300; const int32_t CV_WAIT_SCREENOFF_MS_MAX = 3000; const int32_t CV_WAIT_SCREENOFF_MS = 1500; const int32_t CV_WAIT_BUFFER_AVAILABLE_MS = 8 * 1000 * 1000; const int32_t CV_WAIT_SCBSWITCH_MS = 3000; const int64_t SWITCH_USER_DISPLAYMODE_CHANGE_DELAY = 500; const std::string STATUS_FOLD_HALF = "-z"; const std::string STATUS_EXPAND = "-y"; const std::string STATUS_FOLD = "-p"; const std::string SETTING_LOCKED_KEY = "settings.general.accelerometer_rotation_status"; const ScreenId SCREEN_ID_DEFAULT = 0; const ScreenId SCREEN_ID_FULL = 0; const ScreenId SCREEN_ID_MAIN = 5; const ScreenId SCREEN_ID_PC = 4; const ScreenId SCREEN_ID_PC_MAIN = 9; const ScreenId MINIMUM_VIRTUAL_SCREEN_ID = 1000; constexpr int32_t INVALID_UID = -1; constexpr int32_t INVALID_USER_ID = -1; constexpr int32_t INVALID_SCB_PID = -1; constexpr int32_t BASE_USER_RANGE = 200000; static bool g_foldScreenFlag = system::GetParameter("const.window.foldscreen.type", "") != ""; static int32_t g_screenRotationOffSet = system::GetIntParameter("const.fold.screen_rotation.offset", 0); static const int32_t ROTATION_90 = 1; static const int32_t ROTATION_270 = 3; static const int32_t AUTO_ROTATE_OFF = 0; static const int NOTIFY_EVENT_FOR_DUAL_FAILED = 0; static const int NOTIFY_EVENT_FOR_DUAL_SUCESS = 1; static const int NO_NEED_NOTIFY_EVENT_FOR_DUAL = 2; const unsigned int XCOLLIE_TIMEOUT_10S = 10; const unsigned int XCOLLIE_TIMEOUT_5S = 5; constexpr int32_t CAST_WIRED_PROJECTION_START = 1005; constexpr int32_t CAST_WIRED_PROJECTION_STOP = 1007; constexpr int32_t RES_FAILURE_FOR_PRIVACY_WINDOW = -2; constexpr int32_t REMOVE_DISPLAY_MODE = 0; constexpr int32_t IRREGULAR_REFRESH_RATE_SKIP_THRETHOLD = 10; const int32_t ROTATE_POLICY = system::GetIntParameter("const.window.device.rotate_policy", 0); constexpr int32_t FOLDABLE_DEVICE { 2 }; constexpr float DEFAULT_PIVOT = 0.5f; constexpr float DEFAULT_SCALE = 1.0f; static const constexpr char* SET_SETTING_DPI_KEY {"default_display_dpi"}; // based on the bundle_util inline int32_t GetUserIdByCallingUid() { int32_t uid = IPCSkeleton::GetCallingUid(); TLOGD(WmsLogTag::WMS_MULTI_USER, "get calling uid(%{public}d)", uid); if (uid <= INVALID_UID) { TLOGE(WmsLogTag::WMS_MULTI_USER, "uid is illegal: %{public}d", uid); return INVALID_USER_ID; } return uid / BASE_USER_RANGE; } } // namespace WM_IMPLEMENT_SINGLE_INSTANCE(ScreenSessionManager) const bool REGISTER_RESULT = !SceneBoardJudgement::IsSceneBoardEnabled() ? false : SystemAbility::MakeAndRegisterAbility(&ScreenSessionManager::GetInstance()); ScreenSessionManager::ScreenSessionManager() : SystemAbility(DISPLAY_MANAGER_SERVICE_SA_ID, true), rsInterface_(RSInterfaces::GetInstance()) { screenEventTracker_.RecordEvent("Dms construct."); LoadScreenSceneXml(); screenOffDelay_ = CV_WAIT_SCREENOFF_MS; taskScheduler_ = std::make_shared(SCREEN_SESSION_MANAGER_THREAD); screenPowerTaskScheduler_ = std::make_shared(SCREEN_SESSION_MANAGER_SCREEN_POWER_THREAD); screenCutoutController_ = new (std::nothrow) ScreenCutoutController(); if (!screenCutoutController_) { TLOGE(WmsLogTag::DMS, "screenCutoutController_ is nullptr"); } sessionDisplayPowerController_ = new SessionDisplayPowerController( std::bind(&ScreenSessionManager::NotifyDisplayStateChange, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4)); if (g_foldScreenFlag) { HandleFoldScreenPowerInit(); } WatchParameter(BOOTEVENT_BOOT_COMPLETED.c_str(), BootFinishedCallback, this); } ScreenRotation ScreenSessionManager::ConvertOffsetToCorrectRotation(int32_t phyOffset) { ScreenRotation offsetRotation = ScreenRotation::ROTATION_0; switch (phyOffset) { case 90: // Rotation 90 degree offsetRotation = ScreenRotation::ROTATION_270; break; case 180: // Rotation 180 degree offsetRotation = ScreenRotation::ROTATION_180; break; case 270: // Rotation 270 degree offsetRotation = ScreenRotation::ROTATION_90; break; default: offsetRotation = ScreenRotation::ROTATION_0; break; } return offsetRotation; } void ScreenSessionManager::HandleFoldScreenPowerInit() { TLOGI(WmsLogTag::DMS, "Enter"); foldScreenController_ = new (std::nothrow) FoldScreenController(displayInfoMutex_, screenPowerTaskScheduler_); if (!foldScreenController_) { TLOGE(WmsLogTag::DMS, "foldScreenController_ is nullptr"); return; } foldScreenController_->SetOnBootAnimation(true); if (FoldScreenStateInternel::IsSingleDisplayPocketFoldDevice()) { SetFoldScreenPowerInit([&]() { foldScreenController_->BootAnimationFinishPowerInit(); FixPowerStatus(); foldScreenController_->SetOnBootAnimation(false); RegisterApplicationStateObserver(); }); } else { // 后续其他设备rs上电规格将陆续迁移到BootAnimationFinishPowerInit中 FoldScreenPowerInit(); } } void ScreenSessionManager::FoldScreenPowerInit() { SetFoldScreenPowerInit([&]() { int64_t timeStamp = 50; #ifdef TP_FEATURE_ENABLE int32_t tpType = 12; std::string fullTpChange = "0"; std::string mainTpChange = "1"; #endif if (!foldScreenController_) { TLOGE(WmsLogTag::DMS, "foldScreenController_ is nullptr"); return; } ScreenId currentScreenId = foldScreenController_->GetCurrentScreenId(); if (currentScreenId == SCREEN_ID_FULL) { TLOGI(WmsLogTag::DMS, "ScreenSessionManager Fold Screen Power Full animation Init 1."); rsInterface_.SetScreenPowerStatus(SCREEN_ID_FULL, ScreenPowerStatus::POWER_STATUS_OFF_FAKE); rsInterface_.SetScreenPowerStatus(SCREEN_ID_MAIN, ScreenPowerStatus::POWER_STATUS_ON); std::this_thread::sleep_for(std::chrono::milliseconds(timeStamp)); TLOGI(WmsLogTag::DMS, "ScreenSessionManager Fold Screen Power Full animation Init 2."); #ifdef TP_FEATURE_ENABLE rsInterface_.SetTpFeatureConfig(tpType, fullTpChange.c_str()); #endif rsInterface_.SetScreenPowerStatus(SCREEN_ID_MAIN, ScreenPowerStatus::POWER_STATUS_OFF); if (foldScreenController_ != nullptr) { foldScreenController_->AddOrRemoveDisplayNodeToTree(SCREEN_ID_MAIN, REMOVE_DISPLAY_MODE); } rsInterface_.SetScreenPowerStatus(SCREEN_ID_FULL, ScreenPowerStatus::POWER_STATUS_ON); } else if (currentScreenId == SCREEN_ID_MAIN) { TLOGI(WmsLogTag::DMS, "ScreenSessionManager Fold Screen Power Main animation Init 3."); rsInterface_.SetScreenPowerStatus(SCREEN_ID_MAIN, ScreenPowerStatus::POWER_STATUS_OFF_FAKE); rsInterface_.SetScreenPowerStatus(SCREEN_ID_FULL, ScreenPowerStatus::POWER_STATUS_ON); std::this_thread::sleep_for(std::chrono::milliseconds(timeStamp)); TLOGI(WmsLogTag::DMS, "ScreenSessionManager Fold Screen Power Main animation Init 4."); #ifdef TP_FEATURE_ENABLE rsInterface_.SetTpFeatureConfig(tpType, mainTpChange.c_str()); #endif rsInterface_.SetScreenPowerStatus(SCREEN_ID_FULL, ScreenPowerStatus::POWER_STATUS_OFF); if (foldScreenController_ != nullptr) { foldScreenController_->AddOrRemoveDisplayNodeToTree(SCREEN_ID_FULL, REMOVE_DISPLAY_MODE); } rsInterface_.SetScreenPowerStatus(SCREEN_ID_MAIN, ScreenPowerStatus::POWER_STATUS_ON); } else { TLOGI(WmsLogTag::DMS, "ScreenSessionManager Fold Screen Power Init, invalid active screen id"); } FixPowerStatus(); foldScreenController_->SetOnBootAnimation(false); RegisterApplicationStateObserver(); }); } void ScreenSessionManager::FixPowerStatus() { if (!PowerMgr::PowerMgrClient::GetInstance().IsScreenOn()) { PowerMgr::PowerMgrClient::GetInstance().WakeupDeviceAsync(); TLOGI(WmsLogTag::DMS, "Fix Screen Power State"); } } void ScreenSessionManager::Init() { if (system::GetParameter("soc.boot.mode", "") != "rescue") { constexpr uint64_t interval = 5 * 1000; // 5 second if (HiviewDFX::Watchdog::GetInstance().AddThread( SCREEN_SESSION_MANAGER_THREAD, taskScheduler_->GetEventHandler(), interval)) { TLOGW(WmsLogTag::DMS, "Add thread %{public}s to watchdog failed.", SCREEN_SESSION_MANAGER_THREAD.c_str()); } if (HiviewDFX::Watchdog::GetInstance().AddThread( SCREEN_SESSION_MANAGER_SCREEN_POWER_THREAD, screenPowerTaskScheduler_->GetEventHandler(), interval)) { TLOGW(WmsLogTag::DMS, "Add thread %{public}s to watchdog failed.", SCREEN_SESSION_MANAGER_SCREEN_POWER_THREAD.c_str()); } } else { TLOGI(WmsLogTag::DMS, "Dms in rescue mode, not need watchdog."); screenEventTracker_.RecordEvent("Dms in rescue mode, not need watchdog."); } auto stringConfig = ScreenSceneConfig::GetStringConfig(); if (stringConfig.count("defaultDisplayCutoutPath") != 0) { std::string defaultDisplayCutoutPath = static_cast(stringConfig["defaultDisplayCutoutPath"]); TLOGD(WmsLogTag::DMS, "defaultDisplayCutoutPath = %{public}s.", defaultDisplayCutoutPath.c_str()); ScreenSceneConfig::SetCutoutSvgPath(GetDefaultScreenId(), defaultDisplayCutoutPath); } RegisterScreenChangeListener(); if (!ScreenSceneConfig::IsSupportRotateWithSensor()) { TLOGI(WmsLogTag::DMS, "Current device type not support SetSensorSubscriptionEnabled."); } else if (GetScreenPower(SCREEN_ID_FULL) == ScreenPowerState::POWER_ON) { // 多屏设备只要有屏幕亮,GetScreenPower获取的任意一块屏幕状态均是ON SetSensorSubscriptionEnabled(); screenEventTracker_.RecordEvent("Dms subscribed to sensor successfully."); } // publish init ScreenSessionPublish::GetInstance().InitPublishEvents(); screenEventTracker_.RecordEvent("Dms init end."); } void ScreenSessionManager::OnStart() { TLOGI(WmsLogTag::DMS, "DMS SA OnStart"); DmsXcollie dmsXcollie("DMS:OnStart", XCOLLIE_TIMEOUT_10S, [this](void *) { screenEventTracker_.LogWarningAllInfos(); }); Init(); sptr dms(this); dms->IncStrongRef(nullptr); if (!Publish(dms)) { TLOGE(WmsLogTag::DMS, "Publish DMS failed"); return; } TLOGI(WmsLogTag::DMS, "DMS SA AddSystemAbilityListener"); (void)AddSystemAbilityListener(SENSOR_SERVICE_ABILITY_ID); screenEventTracker_.RecordEvent("Dms AddSystemAbilityListener finished."); TLOGI(WmsLogTag::DMS, "DMS SA OnStart end"); screenEventTracker_.RecordEvent("Dms onstart end."); } void ScreenSessionManager::OnAddSystemAbility(int32_t systemAbilityId, const std::string& deviceId) { HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "OnAddSystemAbility: %d", systemAbilityId); TLOGI(WmsLogTag::DMS, "receive sa add:%{public}d", systemAbilityId); if (systemAbilityId == SENSOR_SERVICE_ABILITY_ID) { #ifdef SENSOR_ENABLE if (!g_foldScreenFlag) { TLOGI(WmsLogTag::DMS, "current device is not fold phone."); return; } if (!foldScreenController_ || isFoldScreenOuterScreenReady_) { TLOGI(WmsLogTag::DMS, "foldScreenController_ is null or outer screen is not ready."); return; } if (GetDisplayState(foldScreenController_->GetCurrentScreenId()) == DisplayState::ON) { FoldScreenSensorManager::GetInstance().RegisterPostureCallback(); TLOGI(WmsLogTag::DMS, "Recover Posture sensor finished"); } FoldScreenSensorManager::GetInstance().RegisterHallCallback(); TLOGI(WmsLogTag::DMS, "Recover Hall sensor finished"); screenEventTracker_.RecordEvent("Dms recover Posture and Hall sensor finished."); #endif } } DMError ScreenSessionManager::RegisterDisplayManagerAgent( const sptr& displayManagerAgent, DisplayManagerAgentType type) { TLOGI(WmsLogTag::DMS, " called type: %{public}u", type); DmsXcollie dmsXcollie("DMS:RegisterDisplayManagerAgent", XCOLLIE_TIMEOUT_10S); if ((type == DisplayManagerAgentType::SCREEN_EVENT_LISTENER || type == DisplayManagerAgentType::PRIVATE_WINDOW_LISTENER) && !SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "Permission Denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return DMError::DM_ERROR_NOT_SYSTEM_APP; } if (type < DisplayManagerAgentType::DISPLAY_POWER_EVENT_LISTENER || type >= DisplayManagerAgentType::DISPLAY_MANAGER_MAX_AGENT_TYPE) { TLOGE(WmsLogTag::DMS, "DisplayManagerAgentType: %{public}u", static_cast(type)); return DMError::DM_ERROR_INVALID_PARAM; } if ((displayManagerAgent == nullptr) || (displayManagerAgent->AsObject() == nullptr)) { TLOGE(WmsLogTag::DMS, "displayManagerAgent invalid"); return DMError::DM_ERROR_NULLPTR; } return dmAgentContainer_.RegisterAgent(displayManagerAgent, type) ? DMError::DM_OK :DMError::DM_ERROR_NULLPTR; } DMError ScreenSessionManager::UnregisterDisplayManagerAgent( const sptr& displayManagerAgent, DisplayManagerAgentType type) { TLOGI(WmsLogTag::DMS, " called type: %{public}u", type); if ((type == DisplayManagerAgentType::SCREEN_EVENT_LISTENER || type == DisplayManagerAgentType::PRIVATE_WINDOW_LISTENER) && !SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "unregister display manager agent permission denied!"); TLOGE(WmsLogTag::DMS, "calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return DMError::DM_ERROR_NOT_SYSTEM_APP; } if ((displayManagerAgent == nullptr) || (displayManagerAgent->AsObject() == nullptr)) { TLOGE(WmsLogTag::DMS, "displayManagerAgent invalid"); return DMError::DM_ERROR_NULLPTR; } return dmAgentContainer_.UnregisterAgent(displayManagerAgent, type) ? DMError::DM_OK :DMError::DM_ERROR_NULLPTR; } void ScreenSessionManager::LoadScreenSceneXml() { if (ScreenSceneConfig::LoadConfigXml()) { ScreenSceneConfig::DumpConfig(); ConfigureScreenScene(); } } void ScreenSessionManager::ConfigureScreenScene() { auto numbersConfig = ScreenSceneConfig::GetIntNumbersConfig(); auto enableConfig = ScreenSceneConfig::GetEnableConfig(); auto stringConfig = ScreenSceneConfig::GetStringConfig(); ConfigureDpi(); if (numbersConfig.count("defaultDeviceRotationOffset") != 0) { defaultDeviceRotationOffset_ = static_cast(numbersConfig["defaultDeviceRotationOffset"][0]); TLOGD(WmsLogTag::DMS, "defaultDeviceRotationOffset = %{public}u", defaultDeviceRotationOffset_); } if (enableConfig.count("isWaterfallDisplay") != 0) { bool isWaterfallDisplay = static_cast(enableConfig["isWaterfallDisplay"]); TLOGD(WmsLogTag::DMS, "isWaterfallDisplay = %d", isWaterfallDisplay); } if (numbersConfig.count("curvedScreenBoundary") != 0) { std::vector vtBoundary = static_cast>(numbersConfig["curvedScreenBoundary"]); TLOGD(WmsLogTag::DMS, "vtBoundary.size=%{public}u", static_cast(vtBoundary.size())); } if (stringConfig.count("subDisplayCutoutPath") != 0) { std::string subDisplayCutoutPath = static_cast(stringConfig["subDisplayCutoutPath"]); TLOGD(WmsLogTag::DMS, "subDisplayCutoutPath = %{public}s.", subDisplayCutoutPath.c_str()); ScreenSceneConfig::SetSubCutoutSvgPath(subDisplayCutoutPath); } if (stringConfig.count("rotationPolicy") != 0) { std::string rotationPolicy = static_cast(stringConfig["rotationPolicy"]); TLOGD(WmsLogTag::DMS, "rotationPolicy = %{public}s.", rotationPolicy.c_str()); deviceScreenConfig_.rotationPolicy_ = rotationPolicy; } if (stringConfig.count("defaultRotationPolicy") != 0) { std::string defaultRotationPolicy = stringConfig["defaultRotationPolicy"]; TLOGD(WmsLogTag::DMS, "defaultRotationPolicy = %{public}s.", defaultRotationPolicy.c_str()); deviceScreenConfig_.defaultRotationPolicy_ = defaultRotationPolicy; } if (enableConfig.count("isRightPowerButton") != 0) { bool isRightPowerButton = static_cast(enableConfig["isRightPowerButton"]); TLOGD(WmsLogTag::DMS, "isRightPowerButton = %d", isRightPowerButton); deviceScreenConfig_.isRightPowerButton_ = isRightPowerButton; } ConfigureWaterfallDisplayCompressionParams(); ConfigureCastParams(); if (numbersConfig.count("buildInDefaultOrientation") != 0) { Orientation orientation = static_cast(numbersConfig["buildInDefaultOrientation"][0]); TLOGD(WmsLogTag::DMS, "orientation = %d", orientation); } allDisplayPhysicalResolution_ = ScreenSceneConfig::GetAllDisplayPhysicalConfig(); } void ScreenSessionManager::ConfigureDpi() { auto numbersConfig = ScreenSceneConfig::GetIntNumbersConfig(); if (numbersConfig.count("dpi") != 0) { uint32_t densityDpi = static_cast(numbersConfig["dpi"][0]); TLOGI(WmsLogTag::DMS, "densityDpi = %u", densityDpi); if (densityDpi >= DOT_PER_INCH_MINIMUM_VALUE && densityDpi <= DOT_PER_INCH_MAXIMUM_VALUE) { isDensityDpiLoad_ = true; defaultDpi = densityDpi; cachedSettingDpi_ = defaultDpi; densityDpi_ = static_cast(densityDpi) / BASELINE_DENSITY; } } if (numbersConfig.count("subDpi") != 0) { uint32_t subDensityDpi = static_cast(numbersConfig["subDpi"][0]); TLOGI(WmsLogTag::DMS, "subDensityDpi = %u", subDensityDpi); if (subDensityDpi >= DOT_PER_INCH_MINIMUM_VALUE && subDensityDpi <= DOT_PER_INCH_MAXIMUM_VALUE) { isDensityDpiLoad_ = true; subDensityDpi_ = static_cast(subDensityDpi) / BASELINE_DENSITY; } } } void ScreenSessionManager::ConfigureCastParams() { auto stringConfig = ScreenSceneConfig::GetStringConfig(); if (stringConfig.count("castBundleName") == 0) { TLOGE(WmsLogTag::DMS, "not find cast bundleName in config xml"); return; } std::string castBundleName = static_cast(stringConfig["castBundleName"]); TLOGD(WmsLogTag::DMS, "castBundleName = %{public}s", castBundleName.c_str()); ScreenCastConnection::GetInstance().SetBundleName(castBundleName); if (stringConfig.count("castAbilityName") == 0) { TLOGE(WmsLogTag::DMS, "not find cast ability in config xml"); return; } std::string castAbilityName = static_cast(stringConfig["castAbilityName"]); TLOGD(WmsLogTag::DMS, "castAbilityName = %{public}s", castAbilityName.c_str()); ScreenCastConnection::GetInstance().SetAbilityName(castAbilityName); } void ScreenSessionManager::ConfigureWaterfallDisplayCompressionParams() { auto numbersConfig = ScreenSceneConfig::GetIntNumbersConfig(); auto enableConfig = ScreenSceneConfig::GetEnableConfig(); if (enableConfig.count("isWaterfallAreaCompressionEnableWhenHorizontal") != 0) { bool enable = static_cast(enableConfig["isWaterfallAreaCompressionEnableWhenHorizontal"]); TLOGD(WmsLogTag::DMS, "isWaterfallAreaCompressionEnableWhenHorizontal=%d.", enable); } ScreenSceneConfig::SetCurvedCompressionAreaInLandscape(); } void ScreenSessionManager::ConfigureScreenSnapshotParams() { auto stringConfig = ScreenSceneConfig::GetStringConfig(); if (stringConfig.count("screenSnapshotBundleName") == 0) { TLOGE(WmsLogTag::DMS, "not find screen snapshot bundleName in config xml"); return; } std::string screenSnapshotBundleName = static_cast(stringConfig["screenSnapshotBundleName"]); TLOGD(WmsLogTag::DMS, "screenSnapshotBundleName = %{public}s.", screenSnapshotBundleName.c_str()); ScreenSnapshotPickerConnection::GetInstance().SetBundleName(screenSnapshotBundleName); if (stringConfig.count("screenSnapshotAbilityName") == 0) { TLOGE(WmsLogTag::DMS, "not find screen snapshot ability in config xml"); return; } std::string screenSnapshotAbilityName = static_cast(stringConfig["screenSnapshotAbilityName"]); TLOGD(WmsLogTag::DMS, "screenSnapshotAbilityName = %{public}s.", screenSnapshotAbilityName.c_str()); ScreenSnapshotPickerConnection::GetInstance().SetAbilityName(screenSnapshotAbilityName); } void ScreenSessionManager::RegisterScreenChangeListener() { TLOGI(WmsLogTag::DMS, "Register screen change listener."); auto res = rsInterface_.SetScreenChangeCallback( [this](ScreenId screenId, ScreenEvent screenEvent) { OnScreenChange(screenId, screenEvent); }); if (res != StatusCode::SUCCESS) { auto task = [this]() { RegisterScreenChangeListener(); }; taskScheduler_->PostAsyncTask(task, "RegisterScreenChangeListener", 50); // Retry after 50 ms. screenEventTracker_.RecordEvent("Dms OnScreenChange register failed."); } else { screenEventTracker_.RecordEvent("Dms OnScreenChange register success."); } } void ScreenSessionManager::RegisterRefreshRateChangeListener() { static bool isRegisterRefreshRateListener = false; if (!isRegisterRefreshRateListener) { auto res = rsInterface_.RegisterHgmRefreshRateUpdateCallback( [this](uint32_t refreshRate) { OnHgmRefreshRateChange(refreshRate); }); if (res != StatusCode::SUCCESS) { TLOGE(WmsLogTag::DMS, "Register refresh rate mode change listener failed."); screenEventTracker_.RecordEvent("Dms RefreshRateChange register failed."); } else { isRegisterRefreshRateListener = true; screenEventTracker_.RecordEvent("Dms RefreshRateChange register success."); } } } void ScreenSessionManager::OnVirtualScreenChange(ScreenId screenId, ScreenEvent screenEvent) { TLOGI(WmsLogTag::DMS, "Notify scb virtual screen change, ScreenId: %{public}" PRIu64 ", ScreenEvent: %{public}d", screenId, static_cast(screenEvent)); auto screenSession = GetScreenSession(screenId); if (!screenSession) { TLOGE(WmsLogTag::DMS, "screenSession is nullptr"); return; } if (screenEvent == ScreenEvent::CONNECTED) { if (clientProxy_) { clientProxy_->OnScreenConnectionChanged(screenId, ScreenEvent::CONNECTED, screenSession->GetRSScreenId(), screenSession->GetName()); } return; } if (screenEvent == ScreenEvent::DISCONNECTED) { if (clientProxy_) { clientProxy_->OnScreenConnectionChanged(screenId, ScreenEvent::DISCONNECTED, screenSession->GetRSScreenId(), screenSession->GetName()); } } } bool ScreenSessionManager::IsDefaultMirrorMode(ScreenId screenId) { if (screenId != SCREEN_ID_MAIN && screenId != SCREEN_ID_FULL && screenId != SCREEN_ID_PC_MAIN && screenId != SCREEN_ID_PC) { return true; } return false; } void ScreenSessionManager::FreeDisplayMirrorNodeInner(const sptr mirrorSession) { if (mirrorSession == nullptr) { return; } std::shared_ptr displayNode = mirrorSession->GetDisplayNode(); if (displayNode == nullptr) { return; } hdmiScreenCount_ = hdmiScreenCount_ > 0 ? hdmiScreenCount_ - 1 : 0; NotifyCaptureStatusChanged(); displayNode->RemoveFromTree(); mirrorSession->ReleaseDisplayNode(); displayNode = nullptr; auto transactionProxy = RSTransactionProxy::GetInstance(); if (transactionProxy != nullptr) { TLOGI(WmsLogTag::DMS, "FreeDisplayMirrorNodeInner free displayNode"); transactionProxy->FlushImplicitTransaction(); } } void ScreenSessionManager::SetScreenCorrection() { std::ostringstream oss; if (g_foldScreenFlag) { if (FoldScreenStateInternel::IsSingleDisplayPocketFoldDevice()) { auto ret = rsInterface_.SetScreenCorrection(SCREEN_ID_MAIN, static_cast(ROTATION_90)); oss << "main screenRotationOffSet: " << g_screenRotationOffSet << " ret value: " << ret; } else { auto ret = rsInterface_.SetScreenCorrection(SCREEN_ID_FULL, static_cast(g_screenRotationOffSet)); oss << "full screenRotationOffSet: " << g_screenRotationOffSet << " ret value: " << ret; } } else { std::vector phyOffsets = FoldScreenStateInternel::GetPhyRotationOffset(); int32_t phyOffset = static_cast(std::stoi(phyOffsets[0])); ScreenRotation correctRotation = ConvertOffsetToCorrectRotation(phyOffset); auto ret = rsInterface_.SetScreenCorrection(SCREEN_ID_DEFAULT, correctRotation); oss << "phyOffset: " << phyOffset << " correctRotation value: " << static_cast(correctRotation) << " ret value: " << ret; } TLOGW(WmsLogTag::DMS, "%{public}s", oss.str().c_str()); screenEventTracker_.RecordEvent(oss.str()); } void ScreenSessionManager::OnScreenChange(ScreenId screenId, ScreenEvent screenEvent) { std::ostringstream oss; oss << "OnScreenChange triggered. screenId: " << static_cast(screenId) << " screenEvent: " << static_cast(screenEvent); screenEventTracker_.RecordEvent(oss.str()); TLOGI(WmsLogTag::DMS, "screenId: %{public}" PRIu64 " screenEvent: %{public}d", screenId, static_cast(screenEvent)); SetScreenCorrection(); auto screenSession = GetOrCreateScreenSession(screenId); if (!screenSession) { TLOGE(WmsLogTag::DMS, "screenSession is nullptr"); return; } if (foldScreenController_ != nullptr) { screenSession->SetFoldScreen(true); } HandleScreenEvent(screenSession, screenId, screenEvent); } void ScreenSessionManager::NotifyScreenModeChange() { auto task = [=] { auto agents = dmAgentContainer_.GetAgentsByType(DisplayManagerAgentType::SCREEN_MODE_CHANGE_EVENT_LISTENER); if (agents.empty()) { return; } std::vector> screenInfos; std::vector screenIds = GetAllScreenIds(); for (auto screenId : screenIds) { auto screenSession = GetScreenSession(screenId); screenInfos.emplace_back(screenSession->ConvertToScreenInfo()); } for (auto& agent : agents) { int32_t agentPid = dmAgentContainer_.GetAgentPid(agent); if (!IsFreezed(agentPid, DisplayManagerAgentType::SCREEN_MODE_CHANGE_EVENT_LISTENER)) { agent->NotifyScreenModeChange(screenInfos); } } }; taskScheduler_->PostAsyncTask(task, "NotifyScreenModeChange"); } void ScreenSessionManager::SendCastEvent(const bool &isPlugIn) { TLOGI(WmsLogTag::DMS, "SendCastEvent entry isPlugIn:%{public}d", isPlugIn); if (!ScreenCastConnection::GetInstance().CastConnectExtension(static_cast(isPlugIn))) { TLOGE(WmsLogTag::DMS, "CastConnectionExtension failed"); return; } if (!ScreenCastConnection::GetInstance().IsConnectedSync()) { TLOGE(WmsLogTag::DMS, "CastConnectionExtension connected failed"); ScreenCastConnection::GetInstance().CastDisconnectExtension(); return; } MessageParcel data; MessageParcel reply; if (isPlugIn) { ScreenCastConnection::GetInstance().SendMessageToCastService(CAST_WIRED_PROJECTION_START, data, reply); } else { ScreenCastConnection::GetInstance().SendMessageToCastService(CAST_WIRED_PROJECTION_STOP, data, reply); } ScreenCastConnection::GetInstance().CastDisconnectExtension(); } void ScreenSessionManager::NotifyCastWhenScreenConnectChange(bool isConnected) { if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "permission denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return; } if (isConnected) { auto task = [this]() { SendCastEvent(true); ScreenSessionPublish::GetInstance().PublishCastPlugInEvent(); }; taskScheduler_->PostAsyncTask(task, "SendCastEventTrue"); TLOGI(WmsLogTag::DMS, "PostAsyncTask SendCastEventTrue"); } else { auto task = [this]() { SendCastEvent(false); ScreenSessionPublish::GetInstance().PublishCastPlugOutEvent(); }; taskScheduler_->PostAsyncTask(task, "SendCastEventFalse"); TLOGI(WmsLogTag::DMS, "PostAsyncTask SendCastEventFalse"); } } void ScreenSessionManager::PhyMirrorConnectWakeupScreen() { if (ScreenSceneConfig::GetExternalScreenDefaultMode() == "mirror") { TLOGI(WmsLogTag::DMS, "Connect to an external screen to wakeup the phone screen"); FixPowerStatus(); } } void ScreenSessionManager::HandleScreenEvent(sptr screenSession, ScreenId screenId, ScreenEvent screenEvent) { bool phyMirrorEnable = IsDefaultMirrorMode(screenId); if (screenEvent == ScreenEvent::CONNECTED) { if (phyMirrorEnable) { PhyMirrorConnectWakeupScreen(); NotifyCastWhenScreenConnectChange(true); } if (foldScreenController_ != nullptr) { if ((screenId == 0 || (screenId == SCREEN_ID_MAIN && isCoordinationFlag_ ==true)) && clientProxy_) { clientProxy_->OnScreenConnectionChanged(screenId, ScreenEvent::CONNECTED, screenSession->GetRSScreenId(), screenSession->GetName()); } return; } if (clientProxy_ && !phyMirrorEnable) { clientProxy_->OnScreenConnectionChanged(screenId, ScreenEvent::CONNECTED, screenSession->GetRSScreenId(), screenSession->GetName()); } if (phyMirrorEnable) { NotifyScreenConnected(screenSession->ConvertToScreenInfo()); NotifyDisplayCreate(screenSession->ConvertToDisplayInfo()); isPhyScreenConnected_ = true; } return; } else if (screenEvent == ScreenEvent::DISCONNECTED) { if (phyMirrorEnable) { NotifyScreenDisconnected(screenSession->GetScreenId()); NotifyDisplayDestroy(screenSession->GetScreenId()); NotifyCastWhenScreenConnectChange(false); FreeDisplayMirrorNodeInner(screenSession); isPhyScreenConnected_ = false; } if (clientProxy_) { clientProxy_->OnScreenConnectionChanged(screenId, ScreenEvent::DISCONNECTED, screenSession->GetRSScreenId(), screenSession->GetName()); } if (!(screenId == SCREEN_ID_MAIN && isCoordinationFlag_ == true)) { std::lock_guard lock(screenSessionMapMutex_); screenSessionMap_.erase(screenId); } { std::lock_guard lock_phy(phyScreenPropMapMutex_); phyScreenPropMap_.erase(screenId); } TLOGI(WmsLogTag::DMS, "DisconnectScreenSession success. ScreenId: %{public}" PRIu64 "", screenId); } } void ScreenSessionManager::OnHgmRefreshRateChange(uint32_t refreshRate) { GetDefaultScreenId(); TLOGD(WmsLogTag::DMS, "Set refreshRate: %{public}u, defaultscreenid: %{public}" PRIu64"", refreshRate, defaultScreenId_); sptr screenSession = GetScreenSession(defaultScreenId_); if (screenSession) { screenSession->UpdateRefreshRate(refreshRate); NotifyDisplayChanged(screenSession->ConvertToDisplayInfo(), DisplayChangeEvent::UPDATE_REFRESHRATE); } else { TLOGE(WmsLogTag::DMS, "Get default screen session failed."); } return; } sptr ScreenSessionManager::GetScreenSession(ScreenId screenId) const { std::lock_guard lock(screenSessionMapMutex_); if (screenSessionMap_.empty()) { screenEventTracker_.LogWarningAllInfos(); } auto iter = screenSessionMap_.find(screenId); if (iter == screenSessionMap_.end()) { TLOGI(WmsLogTag::DMS, "Error found screen session with id: %{public}" PRIu64"", screenId); return nullptr; } return iter->second; } sptr ScreenSessionManager::GetDefaultScreenSession() { GetDefaultScreenId(); return GetScreenSession(defaultScreenId_); } sptr ScreenSessionManager::HookDisplayInfoByUid(sptr displayInfo, const sptr& screenSession) { if (displayInfo == nullptr) { TLOGI(WmsLogTag::DMS, "ConvertToDisplayInfo error, displayInfo is nullptr."); return nullptr; } auto uid = IPCSkeleton::GetCallingUid(); std::shared_lock lock(hookInfoMutex_); if (displayHookMap_.find(uid) != displayHookMap_.end()) { auto info = displayHookMap_[uid]; TLOGI(WmsLogTag::DMS, "hW: %{public}u, hH: %{public}u, hD: %{public}f, hR: %{public}u, hER: %{public}d, " "dW: %{public}u, dH: %{public}u, dR: %{public}u, dO: %{public}u", info.width_, info.height_, info.density_, info.rotation_, info.enableHookRotation_, displayInfo->GetWidth(), displayInfo->GetHeight(), displayInfo->GetRotation(), displayInfo->GetDisplayOrientation()); displayInfo->SetWidth(info.width_); displayInfo->SetHeight(info.height_); displayInfo->SetVirtualPixelRatio(info.density_); if (info.enableHookRotation_) { if (screenSession) { Rotation targetRotation = screenSession->ConvertIntToRotation(static_cast(info.rotation_)); displayInfo->SetRotation(targetRotation); DisplayOrientation targetOrientation = screenSession->CalcDisplayOrientation(targetRotation, FoldDisplayMode::UNKNOWN); TLOGI(WmsLogTag::DMS, "tR: %{public}u, tO: %{public}u", targetRotation, targetOrientation); displayInfo->SetDisplayOrientation(targetOrientation); } else { TLOGI(WmsLogTag::DMS, "ConvertToDisplayInfo error, screenSession is nullptr."); return nullptr; } } } return displayInfo; } sptr ScreenSessionManager::GetDefaultDisplayInfo() { DmsXcollie dmsXcollie("DMS:GetDefaultDisplayInfo", XCOLLIE_TIMEOUT_10S); GetDefaultScreenId(); sptr screenSession = GetScreenSession(defaultScreenId_); std::lock_guard lock_info(displayInfoMutex_); if (screenSession) { sptr displayInfo = screenSession->ConvertToDisplayInfo(); if (displayInfo == nullptr) { TLOGI(WmsLogTag::DMS, "ConvertToDisplayInfo error, displayInfo is nullptr."); return nullptr; } // 在PC/PAD上安装的竖屏应用以及白名单中的应用在显示状态非全屏时需要hook displayinfo displayInfo = HookDisplayInfoByUid(displayInfo, screenSession); return displayInfo; } else { TLOGE(WmsLogTag::DMS, "Get default screen session failed."); return nullptr; } } sptr ScreenSessionManager::GetDisplayInfoById(DisplayId displayId) { TLOGD(WmsLogTag::DMS, "GetDisplayInfoById enter, displayId: %{public}" PRIu64" ", displayId); DmsXcollie dmsXcollie("DMS:GetDisplayInfoById", XCOLLIE_TIMEOUT_10S); std::lock_guard lock(screenSessionMapMutex_); for (auto sessionIt : screenSessionMap_) { auto screenSession = sessionIt.second; if (screenSession == nullptr) { TLOGI(WmsLogTag::DMS, "GetDisplayInfoById screenSession is nullptr, ScreenId: %{public}" PRIu64 "", sessionIt.first); continue; } sptr displayInfo = screenSession->ConvertToDisplayInfo(); if (displayInfo == nullptr) { TLOGI(WmsLogTag::DMS, "ConvertToDisplayInfo error, displayInfo is nullptr."); continue; } if (displayId == displayInfo->GetDisplayId()) { TLOGD(WmsLogTag::DMS, "GetDisplayInfoById success"); displayInfo = HookDisplayInfoByUid(displayInfo, screenSession); return displayInfo; } } TLOGE(WmsLogTag::DMS, "GetDisplayInfoById failed. displayId: %{public}" PRIu64" ", displayId); return nullptr; } sptr ScreenSessionManager::GetDisplayInfoByScreen(ScreenId screenId) { TLOGD(WmsLogTag::DMS, "enter, screenId: %{public}" PRIu64"", screenId); std::lock_guard lock(screenSessionMapMutex_); for (auto sessionIt : screenSessionMap_) { auto screenSession = sessionIt.second; if (screenSession == nullptr) { TLOGI(WmsLogTag::DMS, "GetDisplayInfoByScreen screenSession is nullptr, ScreenId:%{public}" PRIu64"", sessionIt.first); continue; } sptr displayInfo = screenSession->ConvertToDisplayInfo(); if (displayInfo == nullptr) { TLOGI(WmsLogTag::DMS, "GetDisplayInfoByScreen error, displayInfo is nullptr."); continue; } if (screenId == displayInfo->GetScreenId()) { return displayInfo; } } TLOGE(WmsLogTag::DMS, "GetDisplayInfoByScreen failed. screenId: %{public}" PRIu64" ", screenId); return nullptr; } std::vector ScreenSessionManager::GetAllDisplayIds() { TLOGI(WmsLogTag::DMS, "GetAllDisplayIds enter"); std::vector res; std::lock_guard lock(screenSessionMapMutex_); for (auto sessionIt : screenSessionMap_) { auto screenSession = sessionIt.second; if (screenSession == nullptr) { TLOGE(WmsLogTag::DMS, "GetAllDisplayIds screenSession is nullptr, ScreenId:%{public}" PRIu64"", sessionIt.first); continue; } sptr displayInfo = screenSession->ConvertToDisplayInfo(); if (displayInfo == nullptr) { TLOGE(WmsLogTag::DMS, "GetAllDisplayIds error, displayInfo is nullptr."); continue; } DisplayId displayId = displayInfo->GetDisplayId(); res.push_back(displayId); } return res; } sptr ScreenSessionManager::GetScreenInfoById(ScreenId screenId) { DmsXcollie dmsXcollie("DMS:GetScreenInfoById", XCOLLIE_TIMEOUT_10S); if (!SessionPermission::IsSystemCalling()) { TLOGE(WmsLogTag::DMS, "GetScreenInfoById permission denied!"); TLOGE(WmsLogTag::DMS, "calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return nullptr; } auto screenSession = GetScreenSession(screenId); if (screenSession == nullptr) { TLOGE(WmsLogTag::DMS, "GetScreenInfoById cannot find screenInfo: %{public}" PRIu64"", screenId); return nullptr; } return screenSession->ConvertToScreenInfo(); } DMError ScreenSessionManager::SetScreenActiveMode(ScreenId screenId, uint32_t modeId) { TLOGI(WmsLogTag::DMS, "SetScreenActiveMode: ScreenId: %{public}" PRIu64", modeId: %{public}u", screenId, modeId); if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "Permission Denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return DMError::DM_ERROR_NOT_SYSTEM_APP; } if (screenId == SCREEN_ID_INVALID) { TLOGE(WmsLogTag::DMS, "SetScreenActiveMode: invalid screenId"); return DMError::DM_ERROR_NULLPTR; } { sptr screenSession = GetScreenSession(screenId); if (screenSession == nullptr) { TLOGE(WmsLogTag::DMS, "SetScreenActiveMode: Get ScreenSession failed"); return DMError::DM_ERROR_NULLPTR; } ScreenId rsScreenId = SCREEN_ID_INVALID; if (!screenIdManager_.ConvertToRsScreenId(screenId, rsScreenId)) { TLOGE(WmsLogTag::DMS, "SetScreenActiveMode: No corresponding rsId"); return DMError::DM_ERROR_NULLPTR; } HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "ssm:SetScreenActiveMode(%" PRIu64", %u)", screenId, modeId); rsInterface_.SetScreenActiveMode(rsScreenId, modeId); screenSession->activeIdx_ = static_cast(modeId); screenSession->UpdatePropertyByActiveMode(); ScreenProperty property = screenSession->GetScreenProperty(); property.SetPropertyChangeReason("active mode change"); screenSession->PropertyChange(property, ScreenPropertyChangeReason::CHANGE_MODE); NotifyScreenChanged(screenSession->ConvertToScreenInfo(), ScreenChangeEvent::CHANGE_MODE); NotifyDisplayChanged(screenSession->ConvertToDisplayInfo(), DisplayChangeEvent::DISPLAY_SIZE_CHANGED); } return DMError::DM_OK; } bool ScreenSessionManager::ConvertScreenIdToRsScreenId(ScreenId screenId, ScreenId& rsScreenId) { return screenIdManager_.ConvertToRsScreenId(screenId, rsScreenId); } void ScreenSessionManager::UpdateDisplayHookInfo(int32_t uid, bool enable, const DMHookInfo& hookInfo) { TLOGD(WmsLogTag::DMS, "DisplayHookInfo will update"); if (!SessionPermission::IsSystemCalling()) { TLOGE(WmsLogTag::DMS, "UpdateDisplayHookInfo permission denied!"); return; } std::unique_lock lock(hookInfoMutex_); if (enable) { if (uid != 0) { displayHookMap_[uid] = hookInfo; } } else { displayHookMap_.erase(uid); } } bool ScreenSessionManager::IsFreezed(const int32_t& agentPid, const DisplayManagerAgentType& agentType) { std::lock_guard lock(freezedPidListMutex_); if (freezedPidList_.count(agentPid) == 0) { return false; } // 冻结的应用记录应用 pid 和注册的 agentType if (pidAgentTypeMap_.count(agentPid) == 0) { std::set agentTypes = { agentType }; pidAgentTypeMap_[agentPid] = agentTypes; } else { pidAgentTypeMap_[agentPid].insert(agentType); } TLOGD(WmsLogTag::DMS, "Agent is freezed, no need notify. PID: %{public}d.", agentPid); return true; } void ScreenSessionManager::NotifyScreenChanged(sptr screenInfo, ScreenChangeEvent event) { if (screenInfo == nullptr) { TLOGE(WmsLogTag::DMS, "NotifyScreenChanged error, screenInfo is nullptr."); return; } { std::lock_guard lock(lastStatusUpdateMutex_); lastScreenChangeEvent_ = event; } auto task = [=] { TLOGI(WmsLogTag::DMS, "NotifyScreenChanged, screenId:%{public}" PRIu64"", screenInfo->GetScreenId()); auto agents = dmAgentContainer_.GetAgentsByType(DisplayManagerAgentType::SCREEN_EVENT_LISTENER); if (agents.empty()) { TLOGI(WmsLogTag::DMS, "NotifyScreenChanged agents is empty"); return; } for (auto& agent : agents) { int32_t agentPid = dmAgentContainer_.GetAgentPid(agent); if (!IsFreezed(agentPid, DisplayManagerAgentType::SCREEN_EVENT_LISTENER)) { agent->OnScreenChange(screenInfo, event); } } }; taskScheduler_->PostAsyncTask(task, "NotifyScreenChanged:SID:" + std::to_string(screenInfo->GetScreenId())); } DMError ScreenSessionManager::SetVirtualPixelRatio(ScreenId screenId, float virtualPixelRatio) { if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "Permission Denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return DMError::DM_ERROR_NOT_SYSTEM_APP; } sptr screenSession = GetScreenSession(screenId); if (!screenSession) { TLOGE(WmsLogTag::DMS, "screen session is nullptr"); return DMError::DM_ERROR_UNKNOWN; } if (screenSession->isScreenGroup_) { TLOGE(WmsLogTag::DMS, "cannot set virtual pixel ratio to the combination. screen: %{public}" PRIu64"", screenId); return DMError::DM_ERROR_NULLPTR; } if (fabs(screenSession->GetScreenProperty().GetVirtualPixelRatio() - virtualPixelRatio) < 1e-6) { TLOGE(WmsLogTag::DMS, "The density is equivalent to the original value, no update operation is required, aborted."); return DMError::DM_OK; } HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "ssm:SetVirtualPixelRatio(%" PRIu64", %f)", screenId, virtualPixelRatio); screenSession->SetVirtualPixelRatio(virtualPixelRatio); std::map> emptyMap; NotifyDisplayStateChange(GetDefaultScreenId(), screenSession->ConvertToDisplayInfo(), emptyMap, DisplayStateChangeType::VIRTUAL_PIXEL_RATIO_CHANGE); NotifyScreenChanged(screenSession->ConvertToScreenInfo(), ScreenChangeEvent::VIRTUAL_PIXEL_RATIO_CHANGED); NotifyDisplayChanged(screenSession->ConvertToDisplayInfo(), DisplayChangeEvent::DISPLAY_VIRTUAL_PIXEL_RATIO_CHANGED); return DMError::DM_OK; } DMError ScreenSessionManager::SetVirtualPixelRatioSystem(ScreenId screenId, float virtualPixelRatio) { if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "Permission Denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return DMError::DM_ERROR_NOT_SYSTEM_APP; } if (clientProxy_) { clientProxy_->SetVirtualPixelRatioSystem(screenId, virtualPixelRatio); } return DMError::DM_OK; } DMError ScreenSessionManager::SetResolution(ScreenId screenId, uint32_t width, uint32_t height, float virtualPixelRatio) { TLOGI(WmsLogTag::DMS, "SetResolution ScreenId: %{public}" PRIu64 ", w: %{public}u, h: %{public}u, virtualPixelRatio: %{public}f", screenId, width, height, virtualPixelRatio); if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "SetResolution permission denied! calling pid: %{public}d", IPCSkeleton::GetCallingPid()); return DMError::DM_ERROR_NOT_SYSTEM_APP; } if (screenId == SCREEN_ID_INVALID) { TLOGE(WmsLogTag::DMS, "SetResolution: invalid screenId"); return DMError::DM_ERROR_NULLPTR; } sptr screenSession = GetScreenSession(screenId); if (screenSession == nullptr) { TLOGE(WmsLogTag::DMS, "SetResolution: Get ScreenSession failed"); return DMError::DM_ERROR_NULLPTR; } sptr screenSessionModes = screenSession->GetActiveScreenMode(); if (screenSessionModes == nullptr) { TLOGE(WmsLogTag::DMS, "SetResolution: Get screenSessionModes failed"); return DMError::DM_ERROR_NULLPTR; } if (width <= 0 || width > screenSessionModes->width_ || height <= 0 || height > screenSessionModes->height_ || virtualPixelRatio < (static_cast(DOT_PER_INCH_MINIMUM_VALUE) / DOT_PER_INCH) || virtualPixelRatio > (static_cast(DOT_PER_INCH_MAXIMUM_VALUE) / DOT_PER_INCH)) { TLOGE(WmsLogTag::DMS, "SetResolution invalid param! w:%{public}u h:%{public}u min:%{public}f max:%{public}f", screenSessionModes->width_, screenSessionModes->height_, static_cast(DOT_PER_INCH_MINIMUM_VALUE) / DOT_PER_INCH, static_cast(DOT_PER_INCH_MAXIMUM_VALUE) / DOT_PER_INCH); return DMError::DM_ERROR_INVALID_PARAM; } screenSession->SetDensityInCurResolution(virtualPixelRatio); DMError ret = SetVirtualPixelRatio(screenId, virtualPixelRatio); if (ret != DMError::DM_OK) { TLOGE(WmsLogTag::DMS, "Failed to setVirtualPixelRatio when settingResolution"); screenSession->SetDensityInCurResolution(screenSession->GetScreenProperty().GetVirtualPixelRatio()); return ret; } { HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "ssm:SetResolution(%" PRIu64", %u, %u, %f)", screenId, width, height, virtualPixelRatio); screenSession->UpdatePropertyByResolution(width, height); screenSession->PropertyChange(screenSession->GetScreenProperty(), ScreenPropertyChangeReason::CHANGE_MODE); NotifyScreenChanged(screenSession->ConvertToScreenInfo(), ScreenChangeEvent::CHANGE_MODE); NotifyDisplayChanged(screenSession->ConvertToDisplayInfo(), DisplayChangeEvent::DISPLAY_SIZE_CHANGED); } return DMError::DM_OK; } DMError ScreenSessionManager::GetDensityInCurResolution(ScreenId screenId, float& virtualPixelRatio) { DmsXcollie dmsXcollie("DMS:GetDensityInCurResolution", XCOLLIE_TIMEOUT_10S); sptr screenSession = GetScreenSession(screenId); if (screenSession == nullptr) { TLOGE(WmsLogTag::DMS, "GetDensityInCurResolution: Get ScreenSession failed"); return DMError::DM_ERROR_NULLPTR; } virtualPixelRatio = screenSession->GetScreenProperty().GetDensityInCurResolution(); return DMError::DM_OK; } DMError ScreenSessionManager::GetScreenColorGamut(ScreenId screenId, ScreenColorGamut& colorGamut) { TLOGI(WmsLogTag::DMS, "GetScreenColorGamut::ScreenId: %{public}" PRIu64 "", screenId); if (screenId == SCREEN_ID_INVALID) { TLOGE(WmsLogTag::DMS, "GetScreenColorGamut screenId invalid"); return DMError::DM_ERROR_INVALID_PARAM; } sptr screenSession = GetScreenSession(screenId); if (screenSession == nullptr) { return DMError::DM_ERROR_INVALID_PARAM; } return screenSession->GetScreenColorGamut(colorGamut); } DMError ScreenSessionManager::SetScreenColorGamut(ScreenId screenId, int32_t colorGamutIdx) { if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "set screen color gamut permission denied!"); return DMError::DM_ERROR_NOT_SYSTEM_APP; } TLOGI(WmsLogTag::DMS, "SetScreenColorGamut::ScreenId: %{public}" PRIu64 ", colorGamutIdx %{public}d", screenId, colorGamutIdx); if (screenId == SCREEN_ID_INVALID) { TLOGE(WmsLogTag::DMS, "SetScreenColorGamut screenId invalid"); return DMError::DM_ERROR_INVALID_PARAM; } sptr screenSession = GetScreenSession(screenId); if (screenSession == nullptr) { return DMError::DM_ERROR_INVALID_PARAM; } return screenSession->SetScreenColorGamut(colorGamutIdx); } DMError ScreenSessionManager::GetScreenGamutMap(ScreenId screenId, ScreenGamutMap& gamutMap) { TLOGI(WmsLogTag::DMS, "GetScreenGamutMap::ScreenId: %{public}" PRIu64 "", screenId); if (screenId == SCREEN_ID_INVALID) { TLOGE(WmsLogTag::DMS, "GetScreenGamutMap screenId invalid"); return DMError::DM_ERROR_INVALID_PARAM; } sptr screenSession = GetScreenSession(screenId); if (screenSession == nullptr) { return DMError::DM_ERROR_INVALID_PARAM; } return screenSession->GetScreenGamutMap(gamutMap); } DMError ScreenSessionManager::SetScreenGamutMap(ScreenId screenId, ScreenGamutMap gamutMap) { if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "set screen gamut map permission denied!"); return DMError::DM_ERROR_NOT_SYSTEM_APP; } TLOGI(WmsLogTag::DMS, "SetScreenGamutMap::ScreenId: %{public}" PRIu64 ", ScreenGamutMap %{public}u", screenId, static_cast(gamutMap)); if (screenId == SCREEN_ID_INVALID) { TLOGE(WmsLogTag::DMS, "SetScreenGamutMap screenId invalid"); return DMError::DM_ERROR_INVALID_PARAM; } sptr screenSession = GetScreenSession(screenId); if (screenSession == nullptr) { return DMError::DM_ERROR_INVALID_PARAM; } return screenSession->SetScreenGamutMap(gamutMap); } DMError ScreenSessionManager::SetScreenColorTransform(ScreenId screenId) { if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "set Screen color transform permission denied!"); return DMError::DM_ERROR_NOT_SYSTEM_APP; } TLOGI(WmsLogTag::DMS, "SetScreenColorTransform::ScreenId: %{public}" PRIu64 "", screenId); if (screenId == SCREEN_ID_INVALID) { TLOGE(WmsLogTag::DMS, "SetScreenColorTransform screenId invalid"); return DMError::DM_ERROR_INVALID_PARAM; } sptr screenSession = GetScreenSession(screenId); if (screenSession == nullptr) { return DMError::DM_ERROR_INVALID_PARAM; } return screenSession->SetScreenColorTransform(); } sptr ScreenSessionManager::CreatePhysicalMirrorSessionInner(ScreenId screenId, ScreenId defScreenId, ScreenProperty property) { sptr screenSession = nullptr; if (system::GetBoolParameter("persist.edm.disallow_mirror", false)) { TLOGW(WmsLogTag::DMS, "mirror disabled by edm!"); return screenSession; } sptr defaultScreen = GetDefaultScreenSession(); if (defaultScreen == nullptr || defaultScreen->GetDisplayNode() == nullptr) { TLOGE(WmsLogTag::DMS, "default screen null"); return screenSession; } NodeId nodeId = defaultScreen->GetDisplayNode()->GetId(); TLOGI(WmsLogTag::DMS, "physical mirror screen nodeId: %{public}" PRIu64 "", nodeId); ScreenSessionConfig config = { .screenId = screenId, .defaultScreenId = defScreenId, .mirrorNodeId = nodeId, .property = property, }; screenSession = new ScreenSession(config, ScreenSessionReason::CREATE_SESSION_FOR_MIRROR); if (!screenSession) { TLOGE(WmsLogTag::DMS, "screenSession is null"); return nullptr; } if (ScreenSceneConfig::GetExternalScreenDefaultMode() == "none") { // pc is none, pad&&phone is mirror screenSession->SetName("ExtendedDisplay"); } else { screenSession->SetName("CastEngine"); } screenSession->SetIsExtend(true); screenSession->SetMirrorScreenType(MirrorScreenType::PHYSICAL_MIRROR); screenSession->SetScreenCombination(ScreenCombination::SCREEN_MIRROR); NotifyScreenChanged(screenSession->ConvertToScreenInfo(), ScreenChangeEvent::SCREEN_SWITCH_CHANGE); hdmiScreenCount_ = hdmiScreenCount_ + 1; NotifyCaptureStatusChanged(); return screenSession; } sptr ScreenSessionManager::GetScreenSessionInner(ScreenId screenId, ScreenProperty property) { ScreenId defScreenId = GetDefaultScreenId(); TLOGI(WmsLogTag::DMS, "GetScreenSessionInner: screenId:%{public}" PRIu64 "", screenId); if (IsDefaultMirrorMode(screenId)) { return CreatePhysicalMirrorSessionInner(screenId, defScreenId, property); } std::string screenName = "UNKNOWN"; if (screenId == SCREEN_ID_MAIN) { screenName = "SubScreen"; } ScreenSessionConfig config = { .screenId = screenId, .defaultScreenId = defScreenId, .name = screenName, .property = property, }; sptr screenSession = nullptr; screenSession = new ScreenSession(config, ScreenSessionReason::CREATE_SESSION_FOR_REAL); screenSession->SetIsExtend(false); return screenSession; } void ScreenSessionManager::CreateScreenProperty(ScreenId screenId, ScreenProperty& property) { int id = HiviewDFX::XCollie::GetInstance().SetTimer("CreateScreenPropertyCallRS", XCOLLIE_TIMEOUT_10S, nullptr, nullptr, HiviewDFX::XCOLLIE_FLAG_LOG); TLOGI(WmsLogTag::DMS, "Call rsInterface_ GetScreenActiveMode ScreenId: %{public}" PRIu64 "", screenId); auto screenMode = rsInterface_.GetScreenActiveMode(screenId); auto screenBounds = RRect({ 0, 0, screenMode.GetScreenWidth(), screenMode.GetScreenHeight() }, 0.0f, 0.0f); auto screenRefreshRate = screenMode.GetScreenRefreshRate(); TLOGI(WmsLogTag::DMS, "Call rsInterface_ GetScreenCapability ScreenId: %{public}" PRIu64 "", screenId); auto screenCapability = rsInterface_.GetScreenCapability(screenId); HiviewDFX::XCollie::GetInstance().CancelTimer(id); TLOGI(WmsLogTag::DMS, "Call RS interface end, create ScreenProperty begin"); property.SetRotation(0.0f); property.SetPhyWidth(screenCapability.GetPhyWidth()); property.SetPhyHeight(screenCapability.GetPhyHeight()); property.SetDpiPhyBounds(screenCapability.GetPhyWidth(), screenCapability.GetPhyHeight()); property.SetPhyBounds(screenBounds); property.SetBounds(screenBounds); property.SetAvailableArea({0, 0, screenMode.GetScreenWidth(), screenMode.GetScreenHeight()}); if (isDensityDpiLoad_) { if (screenId == SCREEN_ID_MAIN) { TLOGI(WmsLogTag::DMS, "subDensityDpi_ = %{public}f", subDensityDpi_); property.SetVirtualPixelRatio(subDensityDpi_); property.SetDefaultDensity(subDensityDpi_); property.SetDensityInCurResolution(subDensityDpi_); } else { TLOGI(WmsLogTag::DMS, "densityDpi_ = %{public}f", densityDpi_); property.SetVirtualPixelRatio(densityDpi_); property.SetDefaultDensity(densityDpi_); property.SetDensityInCurResolution(densityDpi_); } } else { property.UpdateVirtualPixelRatio(screenBounds); } property.SetRefreshRate(screenRefreshRate); property.SetDefaultDeviceRotationOffset(defaultDeviceRotationOffset_); if (foldScreenController_ != nullptr && screenId == 0 && (g_screenRotationOffSet == ROTATION_90 || g_screenRotationOffSet == ROTATION_270)) { screenBounds = RRect({ 0, 0, screenMode.GetScreenHeight(), screenMode.GetScreenWidth() }, 0.0f, 0.0f); property.SetBounds(screenBounds); } property.CalcDefaultDisplayOrientation(); } sptr ScreenSessionManager::GetOrCreateScreenSession(ScreenId screenId) { TLOGI(WmsLogTag::DMS, "GetOrCreateScreenSession ENTER. ScreenId: %{public}" PRIu64 "", screenId); sptr screenSession = GetScreenSession(screenId); if (screenSession) { TLOGI(WmsLogTag::DMS, "screenSession Exist ScreenId: %{public}" PRIu64 "", screenId); return screenSession; } ScreenId rsId = screenId; screenIdManager_.UpdateScreenId(rsId, screenId); ScreenProperty property; CreateScreenProperty(screenId, property); TLOGI(WmsLogTag::DMS, "CreateScreenProperty end"); screenEventTracker_.RecordEvent("CreateScreenProperty by rsInterface success."); { std::lock_guard lock_phy(phyScreenPropMapMutex_); phyScreenPropMap_[screenId] = property; } if (HandleFoldScreenSessionCreate(screenId) == false) { return nullptr; } sptr session = GetScreenSessionInner(screenId, property); if (session == nullptr) { TLOGE(WmsLogTag::DMS, "get screen session fail ScreenId: %{public}" PRIu64, screenId); return session; } session->RegisterScreenChangeListener(this); InitAbstractScreenModesInfo(session); session->groupSmsId_ = 1; { std::lock_guard lock(screenSessionMapMutex_); screenSessionMap_[screenId] = session; } screenEventTracker_.RecordEvent("create screen session success."); SetHdrFormats(screenId, session); SetColorSpaces(screenId, session); RegisterRefreshRateChangeListener(); TLOGI(WmsLogTag::DMS, "CreateScreenSession success. ScreenId: %{public}" PRIu64 "", screenId); return session; } bool ScreenSessionManager::HandleFoldScreenSessionCreate(ScreenId screenId) { if (foldScreenController_ != nullptr) { // sensor may earlier than screen connect, when physical screen property changed, update foldScreenController_->UpdateForPhyScreenPropertyChange(); /* folder screen outer screenId is 5 */ if (screenId == SCREEN_ID_MAIN) { SetPostureAndHallSensorEnabled(); ScreenSensorConnector::SubscribeTentSensor(); isFoldScreenOuterScreenReady_ = true; if (!FoldScreenStateInternel::IsDualDisplayFoldDevice() && isCoordinationFlag_ == false) { return false; } } } return true; } void ScreenSessionManager::SetHdrFormats(ScreenId screenId, sptr& session) { TLOGI(WmsLogTag::DMS, "SetHdrFormats %{public}" PRIu64, screenId); std::vector rsHdrFormat; auto status = rsInterface_.GetScreenSupportedHDRFormats(screenId, rsHdrFormat); if (static_cast(status) != StatusCode::SUCCESS) { TLOGE(WmsLogTag::DMS, "get hdr format failed! status code: %{public}d", status); } else { std::vector hdrFormat(rsHdrFormat.size()); std::transform(rsHdrFormat.begin(), rsHdrFormat.end(), hdrFormat.begin(), [](int val) { return static_cast(val); }); session->SetHdrFormats(std::move(hdrFormat)); } } void ScreenSessionManager::SetColorSpaces(ScreenId screenId, sptr& session) { if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "set Screen color spaces permission denied!"); return; } TLOGI(WmsLogTag::DMS, "SetColorSpaces %{public}" PRIu64, screenId); std::vector rsColorSpace; auto status = rsInterface_.GetScreenSupportedColorSpaces(screenId, rsColorSpace); if (static_cast(status) != StatusCode::SUCCESS) { TLOGE(WmsLogTag::DMS, "get color space failed! status code: %{public}d", status); } else { std::vector colorSpace(rsColorSpace.size()); std::transform(rsColorSpace.begin(), rsColorSpace.end(), colorSpace.begin(), [](int val) { return static_cast(val); }); session->SetColorSpaces(std::move(colorSpace)); } } ScreenId ScreenSessionManager::GetDefaultScreenId() { if (defaultScreenId_ == INVALID_SCREEN_ID) { defaultScreenId_ = rsInterface_.GetDefaultScreenId(); std::ostringstream oss; oss << "Default screen id : " << defaultScreenId_; TLOGI(WmsLogTag::DMS, "%{public}s", oss.str().c_str()); screenEventTracker_.RecordEvent(oss.str()); } return defaultScreenId_; } bool ScreenSessionManager::WakeUpBegin(PowerStateChangeReason reason) { // 该接口当前只有Power调用 HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "[UL_POWER]ssm:WakeUpBegin(%u)", reason); if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "permission denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return false; } currentWakeUpReason_ = reason; TLOGI(WmsLogTag::DMS, "[UL_POWER]WakeUpBegin reason: %{public}u", static_cast(reason)); // 多屏协作灭屏不通知锁屏 if (reason == PowerStateChangeReason::STATE_CHANGE_REASON_COLLABORATION) { isMultiScreenCollaboration_ = true; return true; } lastWakeUpReason_ = reason; return NotifyDisplayPowerEvent(DisplayPowerEvent::WAKE_UP, EventStatus::BEGIN, reason); } bool ScreenSessionManager::WakeUpEnd() { HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "[UL_POWER]ssm:WakeUpEnd"); if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "permission denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return false; } TLOGI(WmsLogTag::DMS, "[UL_POWER]WakeUpEnd enter"); // 多屏协作灭屏不通知锁屏 if (isMultiScreenCollaboration_) { isMultiScreenCollaboration_ = false; return true; } return NotifyDisplayPowerEvent(DisplayPowerEvent::WAKE_UP, EventStatus::END, PowerStateChangeReason::STATE_CHANGE_REASON_INIT); } bool ScreenSessionManager::SuspendBegin(PowerStateChangeReason reason) { // 该接口当前只有Power调用 HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "[UL_POWER]ssm:SuspendBegin(%u)", reason); if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "permission denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return false; } gotScreenlockFingerprint_ = false; TLOGI(WmsLogTag::DMS, "[UL_POWER]Reason: %{public}u", static_cast(reason)); lastWakeUpReason_ = PowerStateChangeReason::STATE_CHANGE_REASON_INIT; if (reason == PowerStateChangeReason::STATE_CHANGE_REASON_PRE_BRIGHT_AUTH_FAIL_SCREEN_OFF) { lastWakeUpReason_ = PowerStateChangeReason::STATE_CHANGE_REASON_PRE_BRIGHT_AUTH_FAIL_SCREEN_OFF; } // 多屏协作灭屏不通知锁屏 gotScreenOffNotify_ = false; sessionDisplayPowerController_->canCancelSuspendNotify_ = true; sessionDisplayPowerController_->SuspendBegin(reason); if (reason == PowerStateChangeReason::STATE_CHANGE_REASON_COLLABORATION) { isMultiScreenCollaboration_ = true; return true; } return NotifyDisplayPowerEvent(DisplayPowerEvent::SLEEP, EventStatus::BEGIN, reason); } bool ScreenSessionManager::SuspendEnd() { if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "permission denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return false; } TLOGI(WmsLogTag::DMS, "[UL_POWER]SuspendEnd enter"); HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "[UL_POWER]ssm:SuspendEnd"); // 多屏协作灭屏不通知锁屏 if (isMultiScreenCollaboration_) { isMultiScreenCollaboration_ = false; return true; } return NotifyDisplayPowerEvent(DisplayPowerEvent::SLEEP, EventStatus::END, PowerStateChangeReason::STATE_CHANGE_REASON_INIT); } bool ScreenSessionManager::IsPreBrightAuthFail(void) { return lastWakeUpReason_ == PowerStateChangeReason:: STATE_CHANGE_REASON_PRE_BRIGHT_AUTH_FAIL_SCREEN_OFF; } bool ScreenSessionManager::BlockSetDisplayState(void) { return prePowerStateChangeReason_ == PowerStateChangeReason::POWER_BUTTON; } bool ScreenSessionManager::SetDisplayState(DisplayState state) { if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "permission denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return false; } if (!sessionDisplayPowerController_) { TLOGE(WmsLogTag::DMS, "[UL_POWER]sessionDisplayPowerController_ is null"); return false; } TLOGI(WmsLogTag::DMS, "[UL_POWER]SetDisplayState enter"); auto screenIds = GetAllScreenIds(); if (screenIds.empty()) { TLOGI(WmsLogTag::DMS, "[UL_POWER]no screen info"); return sessionDisplayPowerController_->SetDisplayState(state); } UpdateDisplayState(screenIds, state); bool ret = sessionDisplayPowerController_->SetDisplayState(state); if (!ret && state == DisplayState::OFF) { state = lastDisplayState_; UpdateDisplayState(screenIds, state); } lastDisplayState_ = state; return ret; } void ScreenSessionManager::UpdateDisplayState(std::vector screenIds, DisplayState state) { for (auto screenId : screenIds) { sptr screenSession = GetScreenSession(screenId); if (screenSession == nullptr) { TLOGW(WmsLogTag::DMS, "[UL_POWER]SetDisplayState cannot get ScreenSession, screenId: %{public}" PRIu64"", screenId); continue; } screenSession->UpdateDisplayState(state); TLOGI(WmsLogTag::DMS, "[UL_POWER]set screenSession displayState property: %{public}u", screenSession->GetScreenProperty().GetDisplayState()); } } void ScreenSessionManager::BlockScreenOnByCV(void) { if (keyguardDrawnDone_ == false) { TLOGI(WmsLogTag::DMS, "[UL_POWER]screenOnCV_ set"); needScreenOnWhenKeyguardNotify_ = true; std::unique_lock lock(screenOnMutex_); if (screenOnCV_.wait_for(lock, std::chrono::milliseconds(CV_WAIT_SCREENON_MS)) == std::cv_status::timeout) { TLOGI(WmsLogTag::DMS, "[UL_POWER]wait ScreenOnCV_ timeout"); } } } void ScreenSessionManager::BlockScreenOffByCV(void) { if (gotScreenOffNotify_ == false) { TLOGI(WmsLogTag::DMS, "[UL_POWER]screenOffCV_ set, delay:%{public}d", screenOffDelay_); needScreenOffNotify_ = true; std::unique_lock lock(screenOffMutex_); if (screenOffCV_.wait_for(lock, std::chrono::milliseconds(screenOffDelay_)) == std::cv_status::timeout) { isScreenLockSuspend_ = false; needScreenOffNotify_ = false; TLOGI(WmsLogTag::DMS, "[UL_POWER]wait ScreenOffCV_ timeout, isScreenLockSuspend_ is false"); } } } bool ScreenSessionManager::TryToCancelScreenOff() { std::lock_guard notifyLock(sessionDisplayPowerController_->notifyMutex_); TLOGI(WmsLogTag::DMS, "[UL_POWER]about to cancel suspend, can:%{public}d, got:%{public}d, need:%{public}d", sessionDisplayPowerController_->canCancelSuspendNotify_, gotScreenOffNotify_, needScreenOffNotify_); if (sessionDisplayPowerController_->canCancelSuspendNotify_) { sessionDisplayPowerController_->needCancelNotify_ = true; TLOGI(WmsLogTag::DMS, "[UL_POWER]notify cancel screenoff"); ScreenSessionManager::GetInstance().NotifyDisplayPowerEvent(DisplayPowerEvent::DISPLAY_OFF_CANCELED, EventStatus::BEGIN, PowerStateChangeReason::STATE_CHANGE_REASON_INIT); return true; } if (gotScreenOffNotify_ == false && needScreenOffNotify_ == true) { std::unique_lock lock(screenOffMutex_); sessionDisplayPowerController_->canceledSuspend_ = true; screenOffCV_.notify_all(); needScreenOffNotify_ = false; TLOGI(WmsLogTag::DMS, "[UL_POWER]cancel wait and notify cancel screenoff"); ScreenSessionManager::GetInstance().NotifyDisplayPowerEvent(DisplayPowerEvent::DISPLAY_OFF_CANCELED, EventStatus::BEGIN, PowerStateChangeReason::STATE_CHANGE_REASON_INIT); return true; } TLOGW(WmsLogTag::DMS, "[UL_POWER]failed to cancel suspend"); return false; } void ScreenSessionManager::ForceSkipScreenOffAnimation() { std::lock_guard notifyLock(sessionDisplayPowerController_->notifyMutex_); TLOGI(WmsLogTag::DMS, "[UL_POWER]about to skip animation, can:%{public}d, got:%{public}d, need:%{public}d", sessionDisplayPowerController_->canCancelSuspendNotify_, gotScreenOffNotify_, needScreenOffNotify_); if (sessionDisplayPowerController_->canCancelSuspendNotify_) { sessionDisplayPowerController_->skipScreenOffBlock_ = true; TLOGI(WmsLogTag::DMS, "[UL_POWER]skip screenoff animation"); return; } if (gotScreenOffNotify_ == false && needScreenOffNotify_ == true) { std::unique_lock lock(screenOffMutex_); screenOffCV_.notify_all(); needScreenOffNotify_ = false; TLOGI(WmsLogTag::DMS, "[UL_POWER]skip wait"); return; } } bool ScreenSessionManager::SetScreenBrightness(uint64_t screenId, uint32_t level) { if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "set screen brightness permission denied!"); return false; } TLOGI(WmsLogTag::DMS, "SetScreenBrightness screenId:%{public}" PRIu64", level:%{public}u,", screenId, level); RSInterfaces::GetInstance().SetScreenBacklight(screenId, level); return true; } uint32_t ScreenSessionManager::GetScreenBrightness(uint64_t screenId) { uint32_t level = static_cast(RSInterfaces::GetInstance().GetScreenBacklight(screenId)); TLOGI(WmsLogTag::DMS, "GetScreenBrightness screenId:%{public}" PRIu64", level:%{public}u,", screenId, level); return level; } int32_t ScreenSessionManager::SetScreenOffDelayTime(int32_t delay) { DmsXcollie dmsXcollie("DMS:SetScreenOffDelayTime", XCOLLIE_TIMEOUT_10S); if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "set screen off delay time permission denied!"); return 0; } if (delay < CV_WAIT_SCREENOFF_MS) { screenOffDelay_ = CV_WAIT_SCREENOFF_MS; } else if (delay > CV_WAIT_SCREENOFF_MS_MAX) { screenOffDelay_ = CV_WAIT_SCREENOFF_MS_MAX; } else { screenOffDelay_ = delay; } TLOGI(WmsLogTag::DMS, "SetScreenOffDelayTime, delay:%{public}d, screenOffDelay_:%{public}d", delay, screenOffDelay_); return screenOffDelay_; } void ScreenSessionManager::SetCameraStatus(int32_t cameraStatus, int32_t cameraPosition) { if ((cameraStatus_ == cameraStatus) && (cameraPosition_ == cameraPosition)) { return; // no need to update } cameraStatus_ = cameraStatus; cameraPosition_ = cameraPosition; TLOGI(WmsLogTag::DMS, "SetCameraStatus, cameraStatus:%{public}d, cameraPosition:%{public}d", cameraStatus, cameraPosition); } bool ScreenSessionManager::IsScreenLockSuspend(void) { return isScreenLockSuspend_; } void ScreenSessionManager::NotifyDisplayStateChange(DisplayId defaultDisplayId, sptr displayInfo, const std::map>& displayInfoMap, DisplayStateChangeType type) { if (clientProxy_) { clientProxy_->OnDisplayStateChanged(defaultDisplayId, displayInfo, displayInfoMap, type); } } void ScreenSessionManager::NotifyScreenshot(DisplayId displayId) { if (clientProxy_) { clientProxy_->OnScreenshot(displayId); } } bool ScreenSessionManager::SetSpecifiedScreenPower(ScreenId screenId, ScreenPowerState state, PowerStateChangeReason reason) { if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "Permission Denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return false; } TLOGI(WmsLogTag::DMS, "[UL_POWER]SetSpecifiedScreenPower: screen id:%{public}" PRIu64 ", state:%{public}u", screenId, state); ScreenPowerStatus status; switch (state) { case ScreenPowerState::POWER_ON: { status = ScreenPowerStatus::POWER_STATUS_ON; break; } case ScreenPowerState::POWER_OFF: { status = ScreenPowerStatus::POWER_STATUS_OFF; break; } default: { TLOGW(WmsLogTag::DMS, "[UL_POWER]SetScreenPowerStatus state not support"); return false; } } CallRsSetScreenPowerStatusSync(screenId, status); if (reason == PowerStateChangeReason::STATE_CHANGE_REASON_COLLABORATION) { return true; } return NotifyDisplayPowerEvent(state == ScreenPowerState::POWER_ON ? DisplayPowerEvent::DISPLAY_ON : DisplayPowerEvent::DISPLAY_OFF, EventStatus::END, reason); } bool ScreenSessionManager::SetScreenPowerForAll(ScreenPowerState state, PowerStateChangeReason reason) { if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "permission denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return false; } TLOGI(WmsLogTag::DMS, "[UL_POWER]state: %{public}u, reason: %{public}u", static_cast(state), static_cast(reason)); ScreenPowerStatus status; if (!GetPowerStatus(state, reason, status)) { return false; } gotScreenOffNotify_ = false; keyguardDrawnDone_ = false; TLOGI(WmsLogTag::DMS, "[UL_POWER]SetScreenPowerForAll keyguardDrawnDone_ is false"); prePowerStateChangeReason_ = reason; return SetScreenPower(status, reason); } bool ScreenSessionManager::GetPowerStatus(ScreenPowerState state, PowerStateChangeReason reason, ScreenPowerStatus& status) { switch (state) { case ScreenPowerState::POWER_ON: { if (reason == PowerStateChangeReason::STATE_CHANGE_REASON_PRE_BRIGHT) { // 预亮屏 status = ScreenPowerStatus::POWER_STATUS_ON_ADVANCED; TLOGI(WmsLogTag::DMS, "[UL_POWER]Set ScreenPowerStatus: POWER_STATUS_ON_ADVANCED"); } else { status = ScreenPowerStatus::POWER_STATUS_ON; TLOGI(WmsLogTag::DMS, "[UL_POWER]Set ScreenPowerStatus: POWER_STATUS_ON"); } break; } case ScreenPowerState::POWER_OFF: { if (reason == PowerStateChangeReason::STATE_CHANGE_REASON_PRE_BRIGHT_AUTH_FAIL_SCREEN_OFF) { // 预亮屏时指纹认证失败 status = ScreenPowerStatus::POWER_STATUS_OFF_ADVANCED; TLOGI(WmsLogTag::DMS, "[UL_POWER]Set ScreenPowerStatus: POWER_STATUS_OFF_ADVANCED"); } else { status = ScreenPowerStatus::POWER_STATUS_OFF; TLOGI(WmsLogTag::DMS, "[UL_POWER]Set ScreenPowerStatus: POWER_STATUS_OFF"); } rsInterface_.MarkPowerOffNeedProcessOneFrame(); break; } case ScreenPowerState::POWER_SUSPEND: { status = ScreenPowerStatus::POWER_STATUS_SUSPEND; TLOGI(WmsLogTag::DMS, "[UL_POWER]Set ScreenPowerStatus: POWER_SUSPEND"); rsInterface_.MarkPowerOffNeedProcessOneFrame(); break; } default: { TLOGW(WmsLogTag::DMS, "[UL_POWER]SetScreenPowerStatus state not support"); return false; } } return true; } void ScreenSessionManager::ExitCoordination(const std::string& reason) { if (GetFoldDisplayMode() != FoldDisplayMode::COORDINATION) { return; } if (foldScreenController_ != nullptr) { TLOGI(WmsLogTag::DMS, "[UL_POWER]ExitCoordination, reason:%{public}s", reason.c_str()); foldScreenController_->ExitCoordination(); } } void ScreenSessionManager::TryToRecoverFoldDisplayMode(ScreenPowerStatus status) { if (foldScreenController_ == nullptr) { TLOGW(WmsLogTag::DMS, "foldScreenController_ is null"); return; } if (status == ScreenPowerStatus::POWER_STATUS_OFF || status == ScreenPowerStatus::POWER_STATUS_OFF_ADVANCED || status == ScreenPowerStatus::POWER_STATUS_OFF_FAKE || status == ScreenPowerStatus::POWER_STATUS_SUSPEND) { foldScreenController_->RecoverDisplayMode(); } } bool ScreenSessionManager::SetScreenPower(ScreenPowerStatus status, PowerStateChangeReason reason) { TLOGI(WmsLogTag::DMS, "[UL_POWER]SetScreenPower enter status:%{public}u", status); auto screenIds = GetAllScreenIds(); if (screenIds.empty()) { TLOGI(WmsLogTag::DMS, "[UL_POWER]SetScreenPower screenIds empty"); return false; } if (status == ScreenPowerStatus::POWER_STATUS_OFF || status == ScreenPowerStatus::POWER_STATUS_SUSPEND) { ExitCoordination("Press PowerKey"); } if (((status == ScreenPowerStatus::POWER_STATUS_OFF || status == ScreenPowerStatus::POWER_STATUS_SUSPEND) && gotScreenlockFingerprint_ == true) && prePowerStateChangeReason_ != PowerStateChangeReason::STATE_CHANGE_REASON_SHUT_DOWN) { gotScreenlockFingerprint_ = false; TLOGI(WmsLogTag::DMS, "[UL_POWER]SetScreenPower screenlockFingerprint or shutdown"); return NotifyDisplayPowerEvent(status == ScreenPowerStatus::POWER_STATUS_ON ? DisplayPowerEvent::DISPLAY_ON : DisplayPowerEvent::DISPLAY_OFF, EventStatus::END, reason); } if (foldScreenController_ != nullptr) { CallRsSetScreenPowerStatusSyncForFold(status); TryToRecoverFoldDisplayMode(status); } else { for (auto screenId : screenIds) { CallRsSetScreenPowerStatusSync(screenId, status); } } HandlerSensor(status, reason); if ((status == ScreenPowerStatus::POWER_STATUS_OFF || status == ScreenPowerStatus::POWER_STATUS_SUSPEND) && gotScreenlockFingerprint_ == true) { gotScreenlockFingerprint_ = false; } return NotifyDisplayPowerEvent(status == ScreenPowerStatus::POWER_STATUS_ON ? DisplayPowerEvent::DISPLAY_ON : DisplayPowerEvent::DISPLAY_OFF, EventStatus::END, reason); } void ScreenSessionManager::SetScreenPowerForFold(ScreenPowerStatus status) { if (foldScreenController_ == nullptr) { TLOGW(WmsLogTag::DMS, "foldScreenController_ is null"); return; } SetScreenPowerForFold(foldScreenController_->GetCurrentScreenId(), status); } void ScreenSessionManager::SetScreenPowerForFold(ScreenId screenId, ScreenPowerStatus status) { rsInterface_.SetScreenPowerStatus(screenId, status); } void ScreenSessionManager::TriggerDisplayModeUpdate(FoldDisplayMode targetDisplayMode) { auto updateDisplayModeTask = [=] { TLOGI(WmsLogTag::DMS, "start change displaymode to lastest mode"); foldScreenController_->SetDisplayMode(targetDisplayMode); }; taskScheduler_->PostAsyncTask(updateDisplayModeTask, "updateDisplayModeTask"); } void ScreenSessionManager::CallRsSetScreenPowerStatusSync(ScreenId screenId, ScreenPowerStatus status) { auto rsSetScreenPowerStatusTask = [=] { rsInterface_.SetScreenPowerStatus(screenId, status); }; screenPowerTaskScheduler_->PostVoidSyncTask(rsSetScreenPowerStatusTask, "rsInterface_.SetScreenPowerStatus task"); } void ScreenSessionManager::CallRsSetScreenPowerStatusSyncForFold(ScreenPowerStatus status) { auto rsSetScreenPowerStatusTask = [=] { if (foldScreenController_ == nullptr) { TLOGW(WmsLogTag::DMS, "foldScreenController_ is null"); return; } rsInterface_.SetScreenPowerStatus(foldScreenController_->GetCurrentScreenId(), status); }; screenPowerTaskScheduler_->PostVoidSyncTask(rsSetScreenPowerStatusTask, "rsInterface_.SetScreenPowerStatus task"); } void ScreenSessionManager::SetKeyguardDrawnDoneFlag(bool flag) { keyguardDrawnDone_ = flag; } void ScreenSessionManager::HandlerSensor(ScreenPowerStatus status, PowerStateChangeReason reason) { if (ScreenSceneConfig::IsSupportRotateWithSensor()) { if (status == ScreenPowerStatus::POWER_STATUS_ON) { DmsXcollie dmsXcollie("DMS:SubscribeRotationSensor", XCOLLIE_TIMEOUT_5S); TLOGI(WmsLogTag::DMS, "subscribe rotation and posture sensor when phone turn on"); ScreenSensorConnector::SubscribeRotationSensor(); #ifdef SENSOR_ENABLE if (g_foldScreenFlag && reason != PowerStateChangeReason::STATE_CHANGE_REASON_DISPLAY_SWITCH) { FoldScreenSensorManager::GetInstance().RegisterPostureCallback(); } else { TLOGI(WmsLogTag::DMS, "not fold product, switch screen reason, failed register posture."); } #endif } else if (status == ScreenPowerStatus::POWER_STATUS_OFF || status == ScreenPowerStatus::POWER_STATUS_SUSPEND) { TLOGI(WmsLogTag::DMS, "unsubscribe rotation and posture sensor when phone turn off"); if (isMultiScreenCollaboration_) { TLOGI(WmsLogTag::DMS, "[UL_POWER]MultiScreenCollaboration, not unsubscribe rotation sensor"); } else { DmsXcollie dmsXcollie("DMS:UnsubscribeRotationSensor", XCOLLIE_TIMEOUT_5S); ScreenSensorConnector::UnsubscribeRotationSensor(); } #ifdef SENSOR_ENABLE if (g_foldScreenFlag && reason != PowerStateChangeReason::STATE_CHANGE_REASON_DISPLAY_SWITCH) { FoldScreenSensorManager::GetInstance().UnRegisterPostureCallback(); } else { TLOGI(WmsLogTag::DMS, "not fold product, switch screen reason, failed unregister posture."); } #endif } else { TLOGI(WmsLogTag::DMS, "SetScreenPower state not support"); screenEventTracker_.RecordEvent("HandlerSensor start!"); } } } void ScreenSessionManager::BootFinishedCallback(const char *key, const char *value, void *context) { if (strcmp(key, BOOTEVENT_BOOT_COMPLETED.c_str()) == 0 && strcmp(value, "true") == 0) { TLOGI(WmsLogTag::DMS, "BootFinishedCallback boot animation finished"); auto &that = *reinterpret_cast(context); that.SetRotateLockedFromSettingData(); that.SetDpiFromSettingData(); that.SetDisplayState(DisplayState::ON); that.RegisterSettingDpiObserver(); if (that.foldScreenPowerInit_ != nullptr) { that.foldScreenPowerInit_(); } that.RegisterSettingRotationObserver(); if (that.defaultDpi) { auto ret = ScreenSettingHelper::SetSettingDefaultDpi(that.defaultDpi, SET_SETTING_DPI_KEY); if (!ret) { TLOGE(WmsLogTag::DMS, "set setting defaultDpi failed"); } else { TLOGI(WmsLogTag::DMS, "set setting defaultDpi:%{public}d", that.defaultDpi); } } } } void ScreenSessionManager::SetFoldScreenPowerInit(std::function foldScreenPowerInit) { foldScreenPowerInit_ = foldScreenPowerInit; } void ScreenSessionManager::SetRotateLockedFromSettingData() { uint32_t autoRotateStatus = AUTO_ROTATE_OFF; // 0代表自动旋转关闭,1代表自动旋转打开 bool islocked = true; // ret为true表示从数据库读到了值,并赋给了autoRotateStatus bool ret = ScreenSettingHelper::GetSettingValue(autoRotateStatus, SETTING_LOCKED_KEY); TLOGI(WmsLogTag::DMS, "get autoRotateStatus from settingdata: %{public}u", autoRotateStatus); if (autoRotateStatus) { islocked =false; } if (ret) { TLOGI(WmsLogTag::DMS, "get islocked success"); SetScreenRotationLockedFromJs(islocked); } } void ScreenSessionManager::RegisterSettingDpiObserver() { TLOGI(WmsLogTag::DMS, "Register Setting Dpi Observer"); SettingObserver::UpdateFunc updateFunc = [&](const std::string& key) { SetDpiFromSettingData(); }; ScreenSettingHelper::RegisterSettingDpiObserver(updateFunc); } void ScreenSessionManager::SetDpiFromSettingData() { uint32_t settingDpi; bool ret = ScreenSettingHelper::GetSettingDpi(settingDpi); if (!ret) { TLOGW(WmsLogTag::DMS, "get setting dpi failed,use default dpi"); settingDpi = defaultDpi; } else { TLOGI(WmsLogTag::DMS, "get setting dpi success,settingDpi: %{public}u", settingDpi); } if (settingDpi >= DOT_PER_INCH_MINIMUM_VALUE && settingDpi <= DOT_PER_INCH_MAXIMUM_VALUE && cachedSettingDpi_ != settingDpi) { cachedSettingDpi_ = settingDpi; float dpi = static_cast(settingDpi) / BASELINE_DENSITY; ScreenId defaultScreenId = GetDefaultScreenId(); SetVirtualPixelRatio(defaultScreenId, dpi); } } std::vector ScreenSessionManager::GetAllScreenIds() { std::vector res; std::lock_guard lock(screenSessionMapMutex_); for (const auto& iter : screenSessionMap_) { res.emplace_back(iter.first); } return res; } DisplayState ScreenSessionManager::GetDisplayState(DisplayId displayId) { return sessionDisplayPowerController_->GetDisplayState(displayId); } void ScreenSessionManager::NotifyDisplayEvent(DisplayEvent event) { TLOGI(WmsLogTag::DMS, "[UL_POWER]NotifyDisplayEvent receive keyguardDrawnDone"); if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "permission denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return; } sessionDisplayPowerController_->NotifyDisplayEvent(event); if (event == DisplayEvent::KEYGUARD_DRAWN) { keyguardDrawnDone_ = true; TLOGI(WmsLogTag::DMS, "[UL_POWER]keyguardDrawnDone_ is true"); if (needScreenOnWhenKeyguardNotify_) { std::unique_lock lock(screenOnMutex_); screenOnCV_.notify_all(); TLOGI(WmsLogTag::DMS, "[UL_POWER]screenOnCV_ notify one"); needScreenOnWhenKeyguardNotify_=false; } } if (event == DisplayEvent::SCREEN_LOCK_SUSPEND) { TLOGI(WmsLogTag::DMS, "[UL_POWER]screen lock suspend"); gotScreenOffNotify_ = true; if (isPhyScreenConnected_) { isScreenLockSuspend_ = false; TLOGI(WmsLogTag::DMS, "[UL_POWER]isScreenLockSuspend__ is false"); } else { isScreenLockSuspend_ = true; } if (needScreenOffNotify_) { ScreenOffCVNotify(); } } if (event == DisplayEvent::SCREEN_LOCK_OFF) { TLOGI(WmsLogTag::DMS, "[UL_POWER]screen lock off"); gotScreenOffNotify_ = true; isScreenLockSuspend_ = false; TLOGI(WmsLogTag::DMS, "[UL_POWER]isScreenLockSuspend__ is false"); if (needScreenOffNotify_) { ScreenOffCVNotify(); } } if (event == DisplayEvent::SCREEN_LOCK_FINGERPRINT) { TLOGI(WmsLogTag::DMS, "[UL_POWER]screen lock fingerprint"); gotScreenOffNotify_ = true; gotScreenlockFingerprint_ = true; if (needScreenOffNotify_) { ScreenOffCVNotify(); } } } void ScreenSessionManager::ScreenOffCVNotify(void) { std::unique_lock lock(screenOffMutex_); screenOffCV_.notify_all(); needScreenOffNotify_ = false; TLOGI(WmsLogTag::DMS, "[UL_POWER]screenOffCV_ notify one"); } ScreenPowerState ScreenSessionManager::GetScreenPower(ScreenId screenId) { if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "permission denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return ScreenPowerState::INVALID_STATE; } auto state = static_cast(RSInterfaces::GetInstance().GetScreenPowerStatus(screenId)); std::ostringstream oss; oss << "GetScreenPower state:" << static_cast(state) << " screenId:" << static_cast(screenId); TLOGI(WmsLogTag::DMS, "%{public}s", oss.str().c_str()); screenEventTracker_.RecordEvent(oss.str()); return state; } DMError ScreenSessionManager::IsScreenRotationLocked(bool& isLocked) { if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "Permission Denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return DMError::DM_ERROR_NOT_SYSTEM_APP; } sptr screenSession = GetDefaultScreenSession(); if (screenSession == nullptr) { TLOGE(WmsLogTag::DMS, "fail to get default screenSession"); return DMError::DM_ERROR_INVALID_PARAM; } isLocked = screenSession->IsScreenRotationLocked(); TLOGI(WmsLogTag::DMS, "IsScreenRotationLocked:isLocked: %{public}u", isLocked); return DMError::DM_OK; } DMError ScreenSessionManager::SetScreenRotationLocked(bool isLocked) { if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "Permission Denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return DMError::DM_ERROR_NOT_SYSTEM_APP; } sptr screenSession = GetDefaultScreenSession(); if (screenSession == nullptr) { TLOGE(WmsLogTag::DMS, "fail to get default screenSession"); return DMError::DM_ERROR_INVALID_PARAM; } screenSession->SetScreenRotationLocked(isLocked); TLOGI(WmsLogTag::DMS, "SetScreenRotationLocked: isLocked: %{public}u", isLocked); return DMError::DM_OK; } DMError ScreenSessionManager::SetScreenRotationLockedFromJs(bool isLocked) { if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "Permission Denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return DMError::DM_ERROR_NOT_SYSTEM_APP; } sptr screenSession = GetDefaultScreenSession(); if (screenSession == nullptr) { TLOGE(WmsLogTag::DMS, "fail to get default screenSession"); return DMError::DM_ERROR_INVALID_PARAM; } screenSession->SetScreenRotationLockedFromJs(isLocked); TLOGI(WmsLogTag::DMS, "isLocked: %{public}u", isLocked); return DMError::DM_OK; } void ScreenSessionManager::NotifyAndPublishEvent(sptr displayInfo, ScreenId screenId, sptr screenSession) { if (displayInfo == nullptr || screenSession == nullptr) { TLOGE(WmsLogTag::DMS, "NotifyAndPublishEvent error, displayInfo or screenSession is nullptr"); return; } NotifyDisplayChanged(displayInfo, DisplayChangeEvent::UPDATE_ROTATION); NotifyScreenChanged(screenSession->ConvertToScreenInfo(), ScreenChangeEvent::UPDATE_ROTATION); UpdateDisplayScaleState(screenId); std::map> emptyMap; NotifyDisplayStateChange(GetDefaultScreenId(), screenSession->ConvertToDisplayInfo(), emptyMap, DisplayStateChangeType::UPDATE_ROTATION); std::string identity = IPCSkeleton::ResetCallingIdentity(); ScreenSessionPublish::GetInstance().PublishDisplayRotationEvent( displayInfo->GetScreenId(), displayInfo->GetRotation()); IPCSkeleton::SetCallingIdentity(identity); } void ScreenSessionManager::UpdateScreenDirectionInfo(ScreenId screenId, float screenComponentRotation, float rotation, float phyRotation, ScreenPropertyChangeType screenPropertyChangeType) { if (screenPropertyChangeType == ScreenPropertyChangeType::ROTATION_END) { TLOGI(WmsLogTag::DMS, "ROTATION_END"); return; } sptr screenSession = GetScreenSession(screenId); if (screenSession == nullptr) { TLOGE(WmsLogTag::DMS, "fail, cannot find screen %{public}" PRIu64"", screenId); return; } screenSession->SetPhysicalRotation(phyRotation); screenSession->SetScreenComponentRotation(screenComponentRotation); screenSession->UpdateRotationOrientation(rotation); TLOGI(WmsLogTag::DMS, "screenId: %{public}" PRIu64 ", rotation: %{public}f, screenComponentRotation: %{public}f", screenId, rotation, screenComponentRotation); } void ScreenSessionManager::UpdateScreenRotationProperty(ScreenId screenId, const RRect& bounds, float rotation, ScreenPropertyChangeType screenPropertyChangeType) { std::ostringstream oss; std::string changeType = TransferPropertyChangeTypeToString(screenPropertyChangeType); oss << "screenId: " << screenId << " rotation: " << rotation << " width: " << bounds.rect_.width_ \ << " height: " << bounds.rect_.height_ << " type: " << changeType; screenEventTracker_.RecordBoundsEvent(oss.str()); if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "update screen rotation property permission denied!"); return; } sptr screenSession = GetScreenSession(screenId); { DmsXcollie dmsXcollie("DMS:UpdateScreenRotationProperty:CacheForRotation", XCOLLIE_TIMEOUT_10S); if (screenPropertyChangeType == ScreenPropertyChangeType::ROTATION_BEGIN) { // Rs is used to mark the start of the rotation animation TLOGI(WmsLogTag::DMS, "EnableCacheForRotation"); RSInterfaces::GetInstance().EnableCacheForRotation(); } else if (screenPropertyChangeType == ScreenPropertyChangeType::ROTATION_END) { // Rs is used to mark the end of the rotation animation TLOGI(WmsLogTag::DMS, "DisableCacheForRotation"); RSInterfaces::GetInstance().DisableCacheForRotation(); return; } else if (screenPropertyChangeType == ScreenPropertyChangeType::ROTATION_UPDATE_PROPERTY_ONLY) { if (screenSession == nullptr) { TLOGE(WmsLogTag::DMS, "fail to update screen rotation property, cannot find screen " "%{public}" PRIu64"", screenId); return; } sptr displayInfo = screenSession->ConvertToDisplayInfo(); TLOGI(WmsLogTag::DMS, "Update Screen Rotation Property Only"); { std::lock_guard lock_info(displayInfoMutex_); screenSession->UpdatePropertyOnly(bounds, rotation, GetFoldDisplayMode()); } NotifyDisplayChanged(displayInfo, DisplayChangeEvent::UPDATE_ROTATION); NotifyScreenChanged(screenSession->ConvertToScreenInfo(), ScreenChangeEvent::UPDATE_ROTATION); return; } } if (screenSession == nullptr) { TLOGE(WmsLogTag::DMS, "fail to update screen rotation property, cannot find screen %{public}" PRIu64"", screenId); return; } { std::lock_guard lock_info(displayInfoMutex_); screenSession->UpdatePropertyAfterRotation(bounds, rotation, GetFoldDisplayMode()); } sptr displayInfo = screenSession->ConvertToDisplayInfo(); NotifyAndPublishEvent(displayInfo, screenId, screenSession); } void ScreenSessionManager::NotifyDisplayChanged(sptr displayInfo, DisplayChangeEvent event) { if (displayInfo == nullptr) { TLOGE(WmsLogTag::DMS, "NotifyDisplayChanged error, displayInfo is nullptr."); return; } auto task = [=] { if (event == DisplayChangeEvent::UPDATE_REFRESHRATE) { TLOGD(WmsLogTag::DMS, "evevt:%{public}d, displayId:%{public}" PRIu64"", event, displayInfo->GetDisplayId()); } else { TLOGI(WmsLogTag::DMS, "evevt:%{public}d, displayId:%{public}" PRIu64"", event, displayInfo->GetDisplayId()); } auto agents = dmAgentContainer_.GetAgentsByType(DisplayManagerAgentType::DISPLAY_EVENT_LISTENER); if (agents.empty()) { TLOGI(WmsLogTag::DMS, "NotifyDisplayChanged agents is empty"); return; } for (auto& agent : agents) { int32_t agentPid = dmAgentContainer_.GetAgentPid(agent); if (!IsFreezed(agentPid, DisplayManagerAgentType::DISPLAY_EVENT_LISTENER)) { agent->OnDisplayChange(displayInfo, event); } } }; taskScheduler_->PostAsyncTask(task, "NotifyDisplayChanged"); } DMError ScreenSessionManager::SetOrientation(ScreenId screenId, Orientation orientation) { if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "Permission Denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return DMError::DM_ERROR_NOT_SYSTEM_APP; } if (orientation < Orientation::UNSPECIFIED || orientation > Orientation::REVERSE_HORIZONTAL) { TLOGE(WmsLogTag::DMS, "set orientation: %{public}u", static_cast(orientation)); return DMError::DM_ERROR_INVALID_PARAM; } sptr screenSession = GetScreenSession(screenId); if (screenSession == nullptr) { TLOGE(WmsLogTag::DMS, "fail to set orientation, cannot find screen %{public}" PRIu64"", screenId); return DMError::DM_ERROR_NULLPTR; } // just for get orientation test screenSession->SetOrientation(orientation); screenSession->ScreenOrientationChange(orientation, GetFoldDisplayMode()); HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "ssm:SetOrientation"); return DMError::DM_OK; } bool ScreenSessionManager::SetRotation(ScreenId screenId, Rotation rotationAfter, bool isFromWindow) { TLOGI(WmsLogTag::DMS, "Enter SetRotation, screenId: %{public}" PRIu64 ", rotation: %{public}u, isFromWindow: %{public}u,", screenId, rotationAfter, isFromWindow); sptr screenSession = GetScreenSession(screenId); if (screenSession == nullptr) { TLOGE(WmsLogTag::DMS, "SetRotation error, cannot get screen with screenId: %{public}" PRIu64, screenId); return false; } if (rotationAfter == screenSession->GetRotation()) { TLOGE(WmsLogTag::DMS, "rotation not changed. screen %{public}" PRIu64" rotation %{public}u", screenId, rotationAfter); return false; } TLOGI(WmsLogTag::DMS, "set orientation. rotation %{public}u", rotationAfter); SetDisplayBoundary(screenSession); screenSession->SetRotation(rotationAfter); screenSession->PropertyChange(screenSession->GetScreenProperty(), ScreenPropertyChangeReason::ROTATION); NotifyScreenChanged(screenSession->ConvertToScreenInfo(), ScreenChangeEvent::UPDATE_ROTATION); NotifyDisplayChanged(screenSession->ConvertToDisplayInfo(), DisplayChangeEvent::UPDATE_ROTATION); return true; } void ScreenSessionManager::SetSensorSubscriptionEnabled() { isAutoRotationOpen_ = system::GetParameter("persist.display.ar.enabled", "1") == "1"; if (!isAutoRotationOpen_) { TLOGE(WmsLogTag::DMS, "autoRotation is not open"); return; } ScreenSensorConnector::SubscribeRotationSensor(); TLOGI(WmsLogTag::DMS, "subscribe rotation sensor successful"); } void ScreenSessionManager::SetPostureAndHallSensorEnabled() { #ifdef SENSOR_ENABLE if (!g_foldScreenFlag) { TLOGI(WmsLogTag::DMS, "current device is not fold phone."); return; } FoldScreenSensorManager::GetInstance().RegisterPostureCallback(); FoldScreenSensorManager::GetInstance().RegisterHallCallback(); TLOGI(WmsLogTag::DMS, "subscribe Posture and Hall sensor successful"); screenEventTracker_.RecordEvent("Dms subscribe Posture and Hall sensor finished."); #endif } bool ScreenSessionManager::SetRotationFromWindow(Rotation targetRotation) { sptr displayInfo = GetDefaultDisplayInfo(); if (displayInfo == nullptr) { return false; } return SetRotation(displayInfo->GetScreenId(), targetRotation, true); } sptr ScreenSessionManager::GetScreenModesByDisplayId(DisplayId displayId) { auto displayInfo = GetDisplayInfoById(displayId); if (displayInfo == nullptr) { TLOGE(WmsLogTag::DMS, "can not get display."); return nullptr; } auto screenInfo = GetScreenInfoById(displayInfo->GetScreenId()); if (screenInfo == nullptr) { TLOGE(WmsLogTag::DMS, "can not get screen."); return nullptr; } auto modes = screenInfo->GetModes(); auto id = screenInfo->GetModeId(); if (id >= modes.size()) { TLOGE(WmsLogTag::DMS, "can not get screenMode."); return nullptr; } return modes[id]; } sptr ScreenSessionManager::GetScreenInfoByDisplayId(DisplayId displayId) { auto displayInfo = GetDisplayInfoById(displayId); if (displayInfo == nullptr) { TLOGE(WmsLogTag::DMS, "can not get displayInfo."); return nullptr; } return GetScreenInfoById(displayInfo->GetScreenId()); } int ScreenSessionManager::NotifyPowerEventForDualDisplay(DisplayPowerEvent event, EventStatus status, PowerStateChangeReason reason) { std::lock_guard lock(screenSessionMapMutex_); if (screenSessionMap_.empty()) { TLOGE(WmsLogTag::DMS, "[UL_POWER]screenSessionMap is empty"); return NOTIFY_EVENT_FOR_DUAL_FAILED; } // The on/off screen will send a notification based on the number of screens. // The dual display device just notify the current screen usage if (FoldScreenStateInternel::IsDualDisplayFoldDevice()) { ScreenId currentScreenId = foldScreenController_->GetCurrentScreenId(); auto iter = screenSessionMap_.find(currentScreenId); if (iter != screenSessionMap_.end() && iter->second != nullptr) { iter->second->PowerStatusChange(event, status, reason); } return NOTIFY_EVENT_FOR_DUAL_SUCESS; } return NO_NEED_NOTIFY_EVENT_FOR_DUAL; } bool ScreenSessionManager::NotifyDisplayPowerEvent(DisplayPowerEvent event, EventStatus status, PowerStateChangeReason reason) { auto agents = dmAgentContainer_.GetAgentsByType(DisplayManagerAgentType::DISPLAY_POWER_EVENT_LISTENER); if (agents.empty()) { TLOGI(WmsLogTag::DMS, "[UL_POWER]NotifyDisplayPowerEvent agents is empty"); return false; } TLOGD(WmsLogTag::DMS, "[UL_POWER]NotifyDisplayPowerEvent"); for (auto& agent : agents) { agent->NotifyDisplayPowerEvent(event, status); } auto ret = NotifyPowerEventForDualDisplay(event, status, reason); if (ret == NOTIFY_EVENT_FOR_DUAL_FAILED) { TLOGE(WmsLogTag::DMS, "[UL_POWER]NotifyPowerEventForDualDisplay ret false"); return false; } else if (ret == NOTIFY_EVENT_FOR_DUAL_SUCESS) { TLOGD(WmsLogTag::DMS, "[UL_POWER]NotifyPowerEventForDualDisplay ret sucess"); return true; } auto screenIds = GetAllScreenIds(); if (screenIds.empty()) { TLOGI(WmsLogTag::DMS, "[UL_POWER]no screenID"); return false; } auto screenId = screenIds[0]; sptr screenSession = GetScreenSession(screenId); if (screenSession == nullptr) { TLOGE(WmsLogTag::DMS, "[UL_POWER]Cannot get ScreenSession, screenId: %{public}" PRIu64"", screenId); return false; } screenSession->PowerStatusChange(event, status, reason); return true; } bool ScreenSessionManager::NotifyDisplayStateChanged(DisplayId id, DisplayState state) { auto agents = dmAgentContainer_.GetAgentsByType(DisplayManagerAgentType::DISPLAY_STATE_LISTENER); if (agents.empty()) { TLOGI(WmsLogTag::DMS, "agents is empty"); return false; } TLOGI(WmsLogTag::DMS, "notify enter!"); for (auto& agent : agents) { agent->NotifyDisplayStateChanged(id, state); } return true; } DMError ScreenSessionManager::GetAllScreenInfos(std::vector>& screenInfos) { if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "Permission Denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return DMError::DM_ERROR_NOT_SYSTEM_APP; } std::vector screenIds = GetAllScreenIds(); for (auto screenId : screenIds) { auto screenInfo = GetScreenInfoById(screenId); if (screenInfo == nullptr) { TLOGE(WmsLogTag::DMS, "GetAllScreenInfos cannot find screenInfo: %{public}" PRIu64"", screenId); continue; } screenInfos.emplace_back(screenInfo); } return DMError::DM_OK; } std::vector ScreenSessionManager::GetAllScreenIds() const { std::vector res; std::lock_guard lock(screenSessionMapMutex_); for (const auto& iter : screenSessionMap_) { res.emplace_back(iter.first); } return res; } DMError ScreenSessionManager::GetScreenSupportedColorGamuts(ScreenId screenId, std::vector& colorGamuts) { TLOGI(WmsLogTag::DMS, "GetScreenSupportedColorGamuts ENTER"); if (!SessionPermission::IsSystemCalling()) { TLOGE(WmsLogTag::DMS, "Permission Denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return DMError::DM_ERROR_NOT_SYSTEM_APP; } sptr screen = GetScreenSession(screenId); if (screen == nullptr) { TLOGE(WmsLogTag::DMS, "GetScreenSupportedColorGamuts nullptr"); return DMError::DM_ERROR_INVALID_PARAM; } return screen->GetScreenSupportedColorGamuts(colorGamuts); } DMError ScreenSessionManager::GetPixelFormat(ScreenId screenId, GraphicPixelFormat& pixelFormat) { TLOGI(WmsLogTag::DMS, "GetPixelFormat::ScreenId: %{public}" PRIu64, screenId); if (screenId == SCREEN_ID_INVALID) { TLOGE(WmsLogTag::DMS, "GetPixelFormat screenId invalid"); return DMError::DM_ERROR_INVALID_PARAM; } sptr screenSession = GetScreenSession(screenId); if (screenSession == nullptr) { return DMError::DM_ERROR_INVALID_PARAM; } return screenSession->GetPixelFormat(pixelFormat); } DMError ScreenSessionManager::SetPixelFormat(ScreenId screenId, GraphicPixelFormat pixelFormat) { if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "set pixel format permission denied!"); return DMError::DM_ERROR_NOT_SYSTEM_APP; } TLOGI(WmsLogTag::DMS, "SetPixelFormat::ScreenId: %{public}" PRIu64 ", pixelFormat %{public}d", screenId, pixelFormat); if (screenId == SCREEN_ID_INVALID) { TLOGE(WmsLogTag::DMS, "SetPixelFormat screenId invalid"); return DMError::DM_ERROR_INVALID_PARAM; } sptr screenSession = GetScreenSession(screenId); if (screenSession == nullptr) { return DMError::DM_ERROR_INVALID_PARAM; } return screenSession->SetPixelFormat(pixelFormat); } DMError ScreenSessionManager::GetSupportedHDRFormats(ScreenId screenId, std::vector& hdrFormats) { TLOGI(WmsLogTag::DMS, "GetSupportedHDRFormats %{public}" PRIu64, screenId); sptr screen = GetScreenSession(screenId); if (screen == nullptr) { TLOGE(WmsLogTag::DMS, "GetSupportedHDRFormats nullptr"); return DMError::DM_ERROR_INVALID_PARAM; } return screen->GetSupportedHDRFormats(hdrFormats); } DMError ScreenSessionManager::GetScreenHDRFormat(ScreenId screenId, ScreenHDRFormat& hdrFormat) { TLOGI(WmsLogTag::DMS, "GetScreenHDRFormat::ScreenId: %{public}" PRIu64, screenId); if (screenId == SCREEN_ID_INVALID) { TLOGE(WmsLogTag::DMS, "screenId invalid"); return DMError::DM_ERROR_INVALID_PARAM; } sptr screenSession = GetScreenSession(screenId); if (screenSession == nullptr) { return DMError::DM_ERROR_INVALID_PARAM; } return screenSession->GetScreenHDRFormat(hdrFormat); } DMError ScreenSessionManager::SetScreenHDRFormat(ScreenId screenId, int32_t modeIdx) { if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "set screen HDR format permission denied!"); return DMError::DM_ERROR_NOT_SYSTEM_APP; } TLOGI(WmsLogTag::DMS, "SetScreenHDRFormat::ScreenId: %{public}" PRIu64 ", modeIdx %{public}d", screenId, modeIdx); if (screenId == SCREEN_ID_INVALID) { TLOGE(WmsLogTag::DMS, "SetScreenHDRFormat screenId invalid"); return DMError::DM_ERROR_INVALID_PARAM; } sptr screenSession = GetScreenSession(screenId); if (screenSession == nullptr) { return DMError::DM_ERROR_INVALID_PARAM; } return screenSession->SetScreenHDRFormat(modeIdx); } DMError ScreenSessionManager::GetSupportedColorSpaces(ScreenId screenId, std::vector& colorSpaces) { TLOGI(WmsLogTag::DMS, "GetSupportedColorSpaces %{public}" PRIu64, screenId); sptr screenSession = GetScreenSession(screenId); if (screenSession == nullptr) { TLOGE(WmsLogTag::DMS, "GetSupportedColorSpaces nullptr"); return DMError::DM_ERROR_INVALID_PARAM; } return screenSession->GetSupportedColorSpaces(colorSpaces); } DMError ScreenSessionManager::GetScreenColorSpace(ScreenId screenId, GraphicCM_ColorSpaceType& colorSpace) { TLOGI(WmsLogTag::DMS, "GetScreenColorSpace::ScreenId: %{public}" PRIu64, screenId); if (screenId == SCREEN_ID_INVALID) { TLOGE(WmsLogTag::DMS, "screenId invalid"); return DMError::DM_ERROR_INVALID_PARAM; } sptr screenSession = GetScreenSession(screenId); if (screenSession == nullptr) { return DMError::DM_ERROR_INVALID_PARAM; } return screenSession->GetScreenColorSpace(colorSpace); } DMError ScreenSessionManager::SetScreenColorSpace(ScreenId screenId, GraphicCM_ColorSpaceType colorSpace) { if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "set screen color space permission denied!"); return DMError::DM_ERROR_NOT_SYSTEM_APP; } TLOGI(WmsLogTag::DMS, "SetScreenColorSpace::ScreenId: %{public}" PRIu64 ", colorSpace %{public}d", screenId, colorSpace); if (screenId == SCREEN_ID_INVALID) { TLOGE(WmsLogTag::DMS, "SetScreenColorSpace screenId invalid"); return DMError::DM_ERROR_INVALID_PARAM; } sptr screenSession = GetScreenSession(screenId); if (screenSession == nullptr) { return DMError::DM_ERROR_INVALID_PARAM; } return screenSession->SetScreenColorSpace(colorSpace); } void ScreenSessionManager::AddVirtualScreenDeathRecipient(const sptr& displayManagerAgent, ScreenId smsScreenId) { if (deathRecipient_ == nullptr) { TLOGI(WmsLogTag::DMS, "CreateVirtualScreen Create deathRecipient"); deathRecipient_ = new(std::nothrow) AgentDeathRecipient([this](const sptr& agent) { OnRemoteDied(agent); }); } if (deathRecipient_ != nullptr) { auto agIter = screenAgentMap_.find(displayManagerAgent); if (agIter == screenAgentMap_.end()) { displayManagerAgent->AddDeathRecipient(deathRecipient_); } } screenAgentMap_[displayManagerAgent].emplace_back(smsScreenId); } ScreenId ScreenSessionManager::CreateVirtualScreen(VirtualScreenOption option, const sptr& displayManagerAgent) { if (!Permission::IsSystemCalling() && !SessionPermission::IsShellCall()) { return ERROR_ID_NOT_SYSTEM_APP; } if (!(Permission::IsSystemCalling() && Permission::CheckCallingPermission(SCREEN_CAPTURE_PERMISSION)) && !SessionPermission::IsShellCall()) { TLOGE(WmsLogTag::DMS, "Permission Denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return SCREEN_ID_INVALID; } ExitCoordination("CreateVirtualScreen"); TLOGI(WmsLogTag::DMS, "ENTER"); if (SessionPermission::IsBetaVersion()) { CheckAndSendHiSysEvent("CREATE_VIRTUAL_SCREEN", "hmos.screenrecorder"); } if (clientProxy_ && option.missionIds_.size() > 0) { std::vector surfaceNodeIds; clientProxy_->OnGetSurfaceNodeIdsFromMissionIdsChanged(option.missionIds_, surfaceNodeIds, false); option.missionIds_ = surfaceNodeIds; } TLOGI(WmsLogTag::DMS, "missionID size:%{public}ud", static_cast(option.missionIds_.size())); ScreenId rsId = rsInterface_.CreateVirtualScreen(option.name_, option.width_, option.height_, option.surface_, SCREEN_ID_INVALID, option.flags_, option.missionIds_); if (rsId == SCREEN_ID_INVALID) { TLOGI(WmsLogTag::DMS, "rsId is invalid"); return SCREEN_ID_INVALID; } TLOGI(WmsLogTag::DMS, "rsId: %{public}" PRIu64"", rsId); HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "ssm:CreateVirtualScreen(%s)", option.name_.c_str()); std::lock_guard lock(screenSessionMapMutex_); ScreenId smsScreenId = SCREEN_ID_INVALID; if (!screenIdManager_.ConvertToSmsScreenId(rsId, smsScreenId)) { smsScreenId = screenIdManager_.CreateAndGetNewScreenId(rsId); auto screenSession = InitVirtualScreen(smsScreenId, rsId, option); if (screenSession == nullptr) { TLOGI(WmsLogTag::DMS, "screenSession is nullptr"); screenIdManager_.DeleteScreenId(smsScreenId); return SCREEN_ID_INVALID; } screenSession->SetName(option.name_); screenSession->SetMirrorScreenType(MirrorScreenType::VIRTUAL_MIRROR); screenSessionMap_.insert(std::make_pair(smsScreenId, screenSession)); if (option.name_ == "CastEngine") { screenSession->SetVirtualScreenFlag(VirtualScreenFlag::CAST); } NotifyScreenConnected(screenSession->ConvertToScreenInfo()); TLOGI(WmsLogTag::DMS, "create screenId: %{public}" PRIu64", rsId: %{public}" PRIu64"", smsScreenId, rsId); if (displayManagerAgent == nullptr) { virtualScreenCount_ = virtualScreenCount_ + 1; NotifyCaptureStatusChanged(); return smsScreenId; } AddVirtualScreenDeathRecipient(displayManagerAgent, smsScreenId); } virtualScreenCount_ = virtualScreenCount_ + 1; NotifyCaptureStatusChanged(); return smsScreenId; } DMError ScreenSessionManager::SetVirtualScreenSurface(ScreenId screenId, sptr surface) { if (!(Permission::IsSystemCalling() && Permission::CheckCallingPermission(SCREEN_CAPTURE_PERMISSION)) && !SessionPermission::IsShellCall()) { TLOGE(WmsLogTag::DMS, "Permission Denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return DMError::DM_ERROR_NOT_SYSTEM_APP; } if (surface == nullptr) { TLOGE(WmsLogTag::DMS, "surface is null"); return DMError::DM_ERROR_INVALID_PARAM; } sptr screenSession = GetScreenSession(screenId); if (screenSession == nullptr) { TLOGE(WmsLogTag::DMS, "No such screen."); return DMError::DM_ERROR_INVALID_PARAM; } TLOGI(WmsLogTag::DMS, "enter set virtual screen surface"); ScreenId rsScreenId; int32_t res = -1; if (screenIdManager_.ConvertToRsScreenId(screenId, rsScreenId)) { sptr pSurface = Surface::CreateSurfaceAsProducer(surface); if (pSurface != nullptr) { res = rsInterface_.SetVirtualScreenSurface(rsScreenId, pSurface); } } if (res != 0) { TLOGE(WmsLogTag::DMS, "fail to set virtual screen surface in RenderService"); return DMError::DM_ERROR_RENDER_SERVICE_FAILED; } return DMError::DM_OK; } DMError ScreenSessionManager::SetVirtualMirrorScreenScaleMode(ScreenId screenId, ScreenScaleMode scaleMode) { if (!SessionPermission::IsSystemCalling()) { TLOGE(WmsLogTag::DMS, "Permission Denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return DMError::DM_ERROR_NOT_SYSTEM_APP; } sptr screenSession = GetScreenSession(screenId); if (screenSession == nullptr) { TLOGE(WmsLogTag::DMS, "No such screen."); return DMError::DM_ERROR_INVALID_PARAM; } ScreenId rsScreenId; if (!screenIdManager_.ConvertToRsScreenId(screenId, rsScreenId)) { TLOGE(WmsLogTag::DMS, "No corresponding rsId"); return DMError::DM_ERROR_INVALID_PARAM; } bool res = rsInterface_.SetVirtualMirrorScreenScaleMode(rsScreenId, scaleMode); if (!res) { TLOGE(WmsLogTag::DMS, "failed in RenderService"); return DMError::DM_ERROR_RENDER_SERVICE_FAILED; } return DMError::DM_OK; } DMError ScreenSessionManager::SetVirtualMirrorScreenCanvasRotation(ScreenId screenId, bool autoRotate) { if (!SessionPermission::IsSystemCalling()) { TLOGE(WmsLogTag::DMS, "Permission Denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return DMError::DM_ERROR_NOT_SYSTEM_APP; } sptr screenSession = GetScreenSession(screenId); if (screenSession == nullptr) { TLOGE(WmsLogTag::DMS, "No such screen."); return DMError::DM_ERROR_INVALID_PARAM; } TLOGI(WmsLogTag::DMS, "enter set virtual mirror screen canvas rotation"); bool res = false; ScreenId rsScreenId; if (!screenIdManager_.ConvertToRsScreenId(screenId, rsScreenId)) { TLOGE(WmsLogTag::DMS, "No corresponding rsId"); return DMError::DM_ERROR_INVALID_PARAM; } res = rsInterface_.SetVirtualMirrorScreenCanvasRotation(rsScreenId, autoRotate); if (!res) { TLOGE(WmsLogTag::DMS, "failed in RenderService"); return DMError::DM_ERROR_RENDER_SERVICE_FAILED; } TLOGI(WmsLogTag::DMS, "set virtual mirror screen canvas rotation success"); return DMError::DM_OK; } DMError ScreenSessionManager::ResizeVirtualScreen(ScreenId screenId, uint32_t width, uint32_t height) { if (!SessionPermission::IsSystemCalling()) { TLOGE(WmsLogTag::DMS, "Permission Denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return DMError::DM_ERROR_NOT_SYSTEM_APP; } TLOGI(WmsLogTag::DMS, "screenId: %{public}" PRIu64", width: %{public}u, height: %{public}u.", screenId, width, height); sptr screenSession = GetScreenSession(screenId); if (screenSession == nullptr) { TLOGE(WmsLogTag::DMS, "No such screen."); return DMError::DM_ERROR_INVALID_PARAM; } ScreenId rsScreenId; if (!screenIdManager_.ConvertToRsScreenId(screenId, rsScreenId)) { TLOGE(WmsLogTag::DMS, "No corresponding rsId"); return DMError::DM_ERROR_INVALID_PARAM; } rsInterface_.ResizeVirtualScreen(rsScreenId, width, height); screenSession->Resize(width, height); screenSession->PropertyChange(screenSession->GetScreenProperty(), ScreenPropertyChangeReason::VIRTUAL_SCREEN_RESIZE); return DMError::DM_OK; } DMError ScreenSessionManager::DestroyVirtualScreen(ScreenId screenId) { if (!SessionPermission::IsSystemCalling()) { TLOGE(WmsLogTag::DMS, "Permission Denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return DMError::DM_ERROR_NOT_SYSTEM_APP; } if (static_cast(screenId) < static_cast(MINIMUM_VIRTUAL_SCREEN_ID)) { TLOGE(WmsLogTag::DMS, "virtual screenId is invalid, id: %{public}" PRIu64"", static_cast(screenId)); return DMError::DM_ERROR_INVALID_PARAM; } // virtual screen destroy callback to notify scb TLOGI(WmsLogTag::DMS, "destroy virtual screen"); OnVirtualScreenChange(screenId, ScreenEvent::DISCONNECTED); ScreenId rsScreenId = SCREEN_ID_INVALID; { std::lock_guard lock(screenSessionMapMutex_); screenIdManager_.ConvertToRsScreenId(screenId, rsScreenId); for (auto &agentIter : screenAgentMap_) { auto iter = std::find(agentIter.second.begin(), agentIter.second.end(), screenId); if (iter != agentIter.second.end()) { iter = agentIter.second.erase(iter); if (agentIter.first != nullptr && agentIter.second.empty()) { screenAgentMap_.erase(agentIter.first); } break; } } } HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "ssm:DestroyVirtualScreen(%" PRIu64")", screenId); auto screen = GetScreenSession(screenId); if (rsScreenId != SCREEN_ID_INVALID && screen != nullptr) { if (CheckScreenInScreenGroup(screen)) { NotifyDisplayDestroy(screenId); } { std::lock_guard lock(screenSessionMapMutex_); auto screenGroup = RemoveFromGroupLocked(screen); if (screenGroup != nullptr) { NotifyScreenGroupChanged(screen->ConvertToScreenInfo(), ScreenGroupChangeEvent::REMOVE_FROM_GROUP); } screenSessionMap_.erase(screenId); } NotifyScreenDisconnected(screenId); TLOGI(WmsLogTag::DMS, "DestroyVirtualScreen success, id: %{public}" PRIu64"", screenId); } screenIdManager_.DeleteScreenId(screenId); virtualScreenCount_ = virtualScreenCount_ > 0 ? virtualScreenCount_ - 1 : 0; NotifyCaptureStatusChanged(); if (rsScreenId == SCREEN_ID_INVALID) { TLOGE(WmsLogTag::DMS, "DestroyVirtualScreen: No corresponding rsScreenId"); return DMError::DM_ERROR_INVALID_PARAM; } rsInterface_.RemoveVirtualScreen(rsScreenId); return DMError::DM_OK; } DMError ScreenSessionManager::DisableMirror(bool disableOrNot) { TLOGI(WmsLogTag::DMS, "DisableMirror %{public}d", disableOrNot); if (!SessionPermission::IsSystemCalling()) { TLOGE(WmsLogTag::DMS, "Permission Denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return DMError::DM_ERROR_NOT_SYSTEM_APP; } TLOGI(WmsLogTag::DMS, "DisableMirror enter %{public}d", disableOrNot); if (disableOrNot) { std::vector screenIds; auto allScreenIds = GetAllScreenIds(); for (auto screenId : allScreenIds) { auto screen = GetScreenSession(screenId); if (screen && screen->GetScreenProperty().GetScreenType() == ScreenType::VIRTUAL) { screenIds.push_back(screenId); } } StopMirror(screenIds); } return DMError::DM_OK; } void ScreenSessionManager::MirrorSwitchNotify(ScreenId screenId) { auto mirrorScreen = GetScreenSession(screenId); if (mirrorScreen != nullptr) { mirrorScreen->SetScreenCombination(ScreenCombination::SCREEN_MIRROR); NotifyScreenChanged(mirrorScreen->ConvertToScreenInfo(), ScreenChangeEvent::SCREEN_SWITCH_CHANGE); } } DMError ScreenSessionManager::MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenIds, ScreenId& screenGroupId) { TLOGI(WmsLogTag::DMS, "enter!"); if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "Permission Denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return DMError::DM_ERROR_NOT_SYSTEM_APP; } if (system::GetBoolParameter("persist.edm.disallow_mirror", false)) { TLOGW(WmsLogTag::DMS, "disabled by edm!"); return DMError::DM_ERROR_INVALID_PERMISSION; } TLOGI(WmsLogTag::DMS, "mainScreenId :%{public}" PRIu64"", mainScreenId); auto allMirrorScreenIds = GetAllValidScreenIds(mirrorScreenIds); auto iter = std::find(allMirrorScreenIds.begin(), allMirrorScreenIds.end(), mainScreenId); if (iter != allMirrorScreenIds.end()) { allMirrorScreenIds.erase(iter); } auto mainScreen = GetScreenSession(mainScreenId); if (mainScreen == nullptr || allMirrorScreenIds.empty()) { TLOGE(WmsLogTag::DMS, "MakeMirror fail. mainScreen :%{public}" PRIu64", screens size:%{public}u", mainScreenId, static_cast(allMirrorScreenIds.size())); return DMError::DM_ERROR_INVALID_PARAM; } HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:MakeMirror start"); TLOGI(WmsLogTag::DMS, "make mirror start"); for (ScreenId screenId : allMirrorScreenIds) { OnVirtualScreenChange(screenId, ScreenEvent::DISCONNECTED); } DMError makeResult = MultiScreenManager::GetInstance().MirrorSwitch(mainScreenId, allMirrorScreenIds, screenGroupId); if (makeResult != DMError::DM_OK) { TLOGE(WmsLogTag::DMS, "MakeMirror set mirror failed."); return makeResult; } for (ScreenId screenId : allMirrorScreenIds) { MirrorSwitchNotify(screenId); } RegisterCastObserver(allMirrorScreenIds); TLOGI(WmsLogTag::DMS, "make mirror notify scb end makeResult=%{public}d", makeResult); HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:MakeMirror end"); return makeResult; } void ScreenSessionManager::RegisterCastObserver(std::vector& mirrorScreenIds) { for (ScreenId screenId : mirrorScreenIds) { if (GetVirtualScreenFlag(screenId) == VirtualScreenFlag::CAST) { mirrorScreenIds_ = mirrorScreenIds; TLOGI(WmsLogTag::DMS, "Register Setting cast Observer"); SettingObserver::UpdateFunc updateFunc = [&](const std::string& key) { SetCastFromSettingData(); }; ScreenSettingHelper::RegisterSettingCastObserver(updateFunc); } } } void ScreenSessionManager::SetCastFromSettingData() { bool enable; bool ret = ScreenSettingHelper::GetSettingCast(enable); if (!ret) { TLOGW(WmsLogTag::DMS, "get setting cast failed, default enable false"); enable = false; } else { TLOGI(WmsLogTag::DMS, "get setting cast success, enable: %{public}u", enable); } for (ScreenId screenId : mirrorScreenIds_) { ScreenId rsScreenId; if (!screenIdManager_.ConvertToRsScreenId(screenId, rsScreenId)) { TLOGE(WmsLogTag::DMS, "No corresponding rsId"); continue; } rsInterface_.SetCastScreenEnableSkipWindow(rsScreenId, enable); } } void ScreenSessionManager::RegisterSettingRotationObserver() { TLOGI(WmsLogTag::DMS, "Register setting rotation observer"); SettingObserver::UpdateFunc updateFunc = [&](const std::string& key) { int32_t rotation = -1; int32_t screenId = -1; if (ScreenSettingHelper::GetSettingRotation(rotation) && ScreenSettingHelper::GetSettingRotationScreenId(screenId)) { TLOGI(WmsLogTag::DMS, "current dms setting rotation:%{public}d, screenId:%{public}d", rotation, screenId); } else { TLOGI(WmsLogTag::DMS, "get current dms setting rotation and screenId failed"); } }; ScreenSettingHelper::RegisterSettingRotationObserver(updateFunc); } DMError ScreenSessionManager::StopMirror(const std::vector& mirrorScreenIds) { if (!SessionPermission::IsSystemCalling()) { TLOGE(WmsLogTag::DMS, "Permission Denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return DMError::DM_ERROR_NOT_SYSTEM_APP; } auto allMirrorScreenIds = GetAllValidScreenIds(mirrorScreenIds); if (allMirrorScreenIds.empty()) { TLOGI(WmsLogTag::DMS, "StopMirror done. screens' size:%{public}u", static_cast(allMirrorScreenIds.size())); return DMError::DM_OK; } DMError ret = StopScreens(allMirrorScreenIds, ScreenCombination::SCREEN_MIRROR); if (ret != DMError::DM_OK) { TLOGE(WmsLogTag::DMS, "StopMirror failed."); return ret; } UnRegisterCastObserver(allMirrorScreenIds); return DMError::DM_OK; } void ScreenSessionManager::UnRegisterCastObserver(std::vector& mirrorScreenIds) { for (ScreenId screenId : mirrorScreenIds) { if (GetVirtualScreenFlag(screenId) == VirtualScreenFlag::CAST) { ScreenSettingHelper::UnregisterSettingCastObserver(); } } } DMError ScreenSessionManager::StopScreens(const std::vector& screenIds, ScreenCombination stopCombination) { for (ScreenId screenId : screenIds) { TLOGI(WmsLogTag::DMS, "StopScreens ScreenId: %{public}" PRIu64"", screenId); auto screen = GetScreenSession(screenId); if (screen == nullptr) { TLOGW(WmsLogTag::DMS, "StopScreens screen:%{public}" PRIu64" is nullptr", screenId); continue; } sptr screenGroup = GetAbstractScreenGroup(screen->groupSmsId_); if (!screenGroup) { TLOGW(WmsLogTag::DMS, "StopScreens groupDmsId:%{public}" PRIu64"is not in smsScreenGroupMap_", screen->groupSmsId_); continue; } if (screenGroup->combination_ != stopCombination) { TLOGW(WmsLogTag::DMS, "StopScreens try to stop screen in another combination"); continue; } if (screenGroup->combination_ == ScreenCombination::SCREEN_MIRROR && screen->screenId_ == screenGroup->mirrorScreenId_) { TLOGW(WmsLogTag::DMS, "StopScreens try to stop main mirror screen"); continue; } bool res = RemoveChildFromGroup(screen, screenGroup); if (res) { NotifyScreenGroupChanged(screen->ConvertToScreenInfo(), ScreenGroupChangeEvent::REMOVE_FROM_GROUP); } } return DMError::DM_OK; } VirtualScreenFlag ScreenSessionManager::GetVirtualScreenFlag(ScreenId screenId) { if (!SessionPermission::IsSystemCalling()) { TLOGE(WmsLogTag::DMS, "Permission Denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return VirtualScreenFlag::DEFAULT; } auto screen = GetScreenSession(screenId); if (screen == nullptr) { TLOGE(WmsLogTag::DMS, "get virtual screen flag screen session null"); return VirtualScreenFlag::DEFAULT; } return screen->GetVirtualScreenFlag(); } DMError ScreenSessionManager::SetVirtualScreenFlag(ScreenId screenId, VirtualScreenFlag screenFlag) { if (!SessionPermission::IsSystemCalling()) { TLOGE(WmsLogTag::DMS, "Permission Denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return DMError::DM_ERROR_NOT_SYSTEM_APP; } if (screenFlag < VirtualScreenFlag::DEFAULT || screenFlag >= VirtualScreenFlag::MAX) { TLOGE(WmsLogTag::DMS, "set virtual screen flag range error"); return DMError::DM_ERROR_INVALID_PARAM; } auto screen = GetScreenSession(screenId); if (screen == nullptr) { TLOGE(WmsLogTag::DMS, "set virtual screen flag screen session null"); return DMError::DM_ERROR_INVALID_PARAM; } screen->SetVirtualScreenFlag(screenFlag); return DMError::DM_OK; } DMError ScreenSessionManager::SetVirtualScreenRefreshRate(ScreenId screenId, uint32_t refreshInterval) { if (!SessionPermission::IsSystemCalling()) { TLOGE(WmsLogTag::DMS, "Permission Denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return DMError::DM_ERROR_NOT_SYSTEM_APP; } TLOGI(WmsLogTag::DMS, "SetVirtualScreenRefreshRate, screenId: %{public}" PRIu64", refreshInterval: %{public}u", screenId, refreshInterval); if (screenId == GetDefaultScreenId()) { TLOGE(WmsLogTag::DMS, "cannot set refresh rate of main screen, main screen id: %{public}" PRIu64".", GetDefaultScreenId()); return DMError::DM_ERROR_INVALID_PARAM; } if (refreshInterval == 0) { TLOGE(WmsLogTag::DMS, "SetVirtualScreenRefreshRate, refresh interval is 0."); return DMError::DM_ERROR_INVALID_PARAM; } auto screenSession = GetScreenSession(screenId); auto defaultScreenSession = GetDefaultScreenSession(); if (screenSession == nullptr || defaultScreenSession == nullptr) { TLOGE(WmsLogTag::DMS, "SetVirtualScreenRefreshRate, screenSession is null."); return DMError::DM_ERROR_INVALID_PARAM; } ScreenId rsScreenId; if (!screenIdManager_.ConvertToRsScreenId(screenId, rsScreenId)) { TLOGE(WmsLogTag::DMS, "SetVirtualScreenRefreshRate, No corresponding rsId."); return DMError::DM_ERROR_INVALID_PARAM; } int32_t res = rsInterface_.SetScreenSkipFrameInterval(rsScreenId, refreshInterval); if (res != StatusCode::SUCCESS) { TLOGE(WmsLogTag::DMS, "SetVirtualScreenRefreshRate, rsInterface error: %{public}d", res); return DMError::DM_ERROR_INVALID_PARAM; } // when skipFrameInterval > 10 means the skipFrameInterval is the virtual screen refresh rate if (refreshInterval > IRREGULAR_REFRESH_RATE_SKIP_THRETHOLD) { screenSession->UpdateRefreshRate(refreshInterval); } else { screenSession->UpdateRefreshRate(defaultScreenSession->GetRefreshRate() / refreshInterval); } TLOGI(WmsLogTag::DMS, "refreshInterval is %{public}d", refreshInterval); return DMError::DM_OK; } DMError ScreenSessionManager::VirtualScreenUniqueSwitch(const std::vector& screenIds) { TLOGI(WmsLogTag::DMS, "enter"); auto defaultScreen = GetDefaultScreenSession(); if (!defaultScreen) { TLOGE(WmsLogTag::DMS, "default screen is nullptr"); return DMError::DM_ERROR_NULLPTR; } defaultScreen->groupSmsId_ = 1; { std::lock_guard lock(screenSessionMapMutex_); auto iter = smsScreenGroupMap_.find(defaultScreen->groupSmsId_); if (iter != smsScreenGroupMap_.end()) { smsScreenGroupMap_.erase(iter); } } DMError uniqueSwitchRet = MultiScreenManager::GetInstance().VirtualScreenUniqueSwitch(defaultScreen, screenIds); TLOGI(WmsLogTag::DMS, "virtual screen unique switch result: %{public}d", uniqueSwitchRet); return uniqueSwitchRet; } DMError ScreenSessionManager::MakeUniqueScreen(const std::vector& screenIds) { if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "Permission Denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return DMError::DM_ERROR_NOT_SYSTEM_APP; } TLOGI(WmsLogTag::DMS, "enter!"); if (screenIds.empty()) { TLOGE(WmsLogTag::DMS, "screen is empty"); return DMError::DM_ERROR_INVALID_PARAM; } ScreenId uniqueScreenId = screenIds[0]; auto uniqueScreen = GetScreenSession(uniqueScreenId); if (uniqueScreen != nullptr) { if (uniqueScreen->GetSourceMode() == ScreenSourceMode::SCREEN_UNIQUE) { TLOGI(WmsLogTag::DMS, "make unique ignore"); return DMError::DM_OK; } return MultiScreenManager::GetInstance().UniqueSwitch(screenIds); } for (auto screenId : screenIds) { ScreenId rsScreenId = SCREEN_ID_INVALID; bool res = ConvertScreenIdToRsScreenId(screenId, rsScreenId); TLOGI(WmsLogTag::DMS, "unique screenId: %{public}" PRIu64" rsScreenId: %{public}" PRIu64"", screenId, rsScreenId); if (!res) { TLOGE(WmsLogTag::DMS, "convert screenId to rsScreenId failed"); continue; } auto screenSession = GetScreenSession(screenId); if (!screenSession) { TLOGE(WmsLogTag::DMS, "screen session is nullptr"); continue; } Rosen::RSDisplayNodeConfig rsConfig; rsConfig.screenId = rsScreenId; screenSession->CreateDisplayNode(rsConfig); screenSession->SetDisplayNodeScreenId(rsScreenId); // notify scb to build Screen widget OnVirtualScreenChange(screenId, ScreenEvent::CONNECTED); } auto transactionProxy = RSTransactionProxy::GetInstance(); if (transactionProxy != nullptr) { TLOGD(WmsLogTag::DMS, "flush data"); transactionProxy->FlushImplicitTransaction(); } TLOGI(WmsLogTag::DMS, "end"); return DMError::DM_OK; } DMError ScreenSessionManager::MakeExpand(std::vector screenId, std::vector startPoint, ScreenId& screenGroupId) { TLOGI(WmsLogTag::DMS, "MakeExpand enter!"); if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "MakeExpand permission denied! pid: %{public}d", IPCSkeleton::GetCallingPid()); return DMError::DM_ERROR_NOT_SYSTEM_APP; } if (screenId.empty() || startPoint.empty() || screenId.size() != startPoint.size()) { TLOGE(WmsLogTag::DMS, "create expand fail, screenId size:%{public}ud,startPoint size:%{public}ud", static_cast(screenId.size()), static_cast(startPoint.size())); return DMError::DM_ERROR_INVALID_PARAM; } std::map pointsMap; uint32_t size = screenId.size(); for (uint32_t i = 0; i < size; i++) { if (pointsMap.find(screenId[i]) != pointsMap.end()) { continue; } pointsMap[screenId[i]] = startPoint[i]; } ScreenId defaultScreenId = GetDefaultScreenId(); auto allExpandScreenIds = GetAllValidScreenIds(screenId); auto iter = std::find(allExpandScreenIds.begin(), allExpandScreenIds.end(), defaultScreenId); if (iter != allExpandScreenIds.end()) { allExpandScreenIds.erase(iter); } if (allExpandScreenIds.empty()) { TLOGE(WmsLogTag::DMS, "allExpandScreenIds is empty. make expand failed."); return DMError::DM_ERROR_NULLPTR; } std::shared_ptr rsDisplayNode; std::vector points; for (uint32_t i = 0; i < allExpandScreenIds.size(); i++) { rsDisplayNode = GetRSDisplayNodeByScreenId(allExpandScreenIds[i]); points.emplace_back(pointsMap[allExpandScreenIds[i]]); if (rsDisplayNode != nullptr) { rsDisplayNode->SetDisplayOffset(pointsMap[allExpandScreenIds[i]].posX_, pointsMap[allExpandScreenIds[i]].posY_); } } HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:MakeExpand"); if (!OnMakeExpand(allExpandScreenIds, points)) { return DMError::DM_ERROR_NULLPTR; } auto screen = GetScreenSession(allExpandScreenIds[0]); if (screen == nullptr || GetAbstractScreenGroup(screen->groupSmsId_) == nullptr) { return DMError::DM_ERROR_NULLPTR; } screenGroupId = screen->groupSmsId_; return DMError::DM_OK; } bool ScreenSessionManager::OnMakeExpand(std::vector screenId, std::vector startPoint) { ScreenId defaultScreenId = GetDefaultScreenId(); TLOGI(WmsLogTag::DMS, "OnMakeExpand, defaultScreenId:%{public}" PRIu64"", defaultScreenId); auto defaultScreen = GetScreenSession(defaultScreenId); if (defaultScreen == nullptr) { TLOGI(WmsLogTag::DMS, "OnMakeExpand failed."); return false; } auto group = GetAbstractScreenGroup(defaultScreen->groupSmsId_); if (group == nullptr) { group = AddToGroupLocked(defaultScreen); if (group == nullptr) { TLOGE(WmsLogTag::DMS, "group is nullptr"); return false; } NotifyScreenGroupChanged(defaultScreen->ConvertToScreenInfo(), ScreenGroupChangeEvent::ADD_TO_GROUP); } bool filterExpandScreen = group->combination_ == ScreenCombination::SCREEN_EXPAND; ChangeScreenGroup(group, screenId, startPoint, filterExpandScreen, ScreenCombination::SCREEN_EXPAND); TLOGI(WmsLogTag::DMS, "OnMakeExpand success"); return true; } DMError ScreenSessionManager::StopExpand(const std::vector& expandScreenIds) { if (!SessionPermission::IsSystemCalling()) { TLOGE(WmsLogTag::DMS, "Permission Denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return DMError::DM_ERROR_NOT_SYSTEM_APP; } auto allExpandScreenIds = GetAllValidScreenIds(expandScreenIds); if (allExpandScreenIds.empty()) { TLOGI(WmsLogTag::DMS, "StopExpand done. screens' size:%{public}u", static_cast(allExpandScreenIds.size())); return DMError::DM_OK; } DMError ret = StopScreens(allExpandScreenIds, ScreenCombination::SCREEN_EXPAND); if (ret != DMError::DM_OK) { TLOGE(WmsLogTag::DMS, "StopExpand stop expand failed."); return ret; } return DMError::DM_OK; } bool ScreenSessionManager::ScreenIdManager::ConvertToRsScreenId(ScreenId smsScreenId, ScreenId& rsScreenId) const { std::shared_lock lock(screenIdMapMutex_); auto iter = sms2RsScreenIdMap_.find(smsScreenId); if (iter == sms2RsScreenIdMap_.end()) { return false; } rsScreenId = iter->second; return true; } ScreenId ScreenSessionManager::ScreenIdManager::ConvertToRsScreenId(ScreenId screenId) const { ScreenId rsScreenId = SCREEN_ID_INVALID; ConvertToRsScreenId(screenId, rsScreenId); return rsScreenId; } ScreenId ScreenSessionManager::ScreenIdManager::ConvertToSmsScreenId(ScreenId rsScreenId) const { ScreenId smsScreenId = SCREEN_ID_INVALID; ConvertToSmsScreenId(rsScreenId, smsScreenId); return smsScreenId; } bool ScreenSessionManager::ScreenIdManager::ConvertToSmsScreenId(ScreenId rsScreenId, ScreenId& smsScreenId) const { std::shared_lock lock(screenIdMapMutex_); auto iter = rs2SmsScreenIdMap_.find(rsScreenId); if (iter == rs2SmsScreenIdMap_.end()) { return false; } smsScreenId = iter->second; return true; } ScreenId ScreenSessionManager::ScreenIdManager::CreateAndGetNewScreenId(ScreenId rsScreenId) { std::unique_lock lock(screenIdMapMutex_); ScreenId smsScreenId = smsScreenCount_++; TLOGI(WmsLogTag::DMS, "CreateAndGetNewScreenId screenId: %{public}" PRIu64"", smsScreenId); if (sms2RsScreenIdMap_.find(smsScreenId) != sms2RsScreenIdMap_.end()) { TLOGW(WmsLogTag::DMS, "CreateAndGetNewScreenId screenId: %{public}" PRIu64" exit", smsScreenId); } sms2RsScreenIdMap_[smsScreenId] = rsScreenId; if (rsScreenId == SCREEN_ID_INVALID) { return smsScreenId; } if (rs2SmsScreenIdMap_.find(rsScreenId) != rs2SmsScreenIdMap_.end()) { TLOGW(WmsLogTag::DMS, "CreateAndGetNewScreenId rsScreenId: %{public}" PRIu64" exit", rsScreenId); } rs2SmsScreenIdMap_[rsScreenId] = smsScreenId; return smsScreenId; } void ScreenSessionManager::ScreenIdManager::UpdateScreenId(ScreenId rsScreenId, ScreenId smsScreenId) { std::unique_lock lock(screenIdMapMutex_); rs2SmsScreenIdMap_[rsScreenId] = smsScreenId; sms2RsScreenIdMap_[smsScreenId] = rsScreenId; } bool ScreenSessionManager::ScreenIdManager::DeleteScreenId(ScreenId smsScreenId) { std::unique_lock lock(screenIdMapMutex_); auto iter = sms2RsScreenIdMap_.find(smsScreenId); if (iter == sms2RsScreenIdMap_.end()) { return false; } ScreenId rsScreenId = iter->second; sms2RsScreenIdMap_.erase(smsScreenId); rs2SmsScreenIdMap_.erase(rsScreenId); return true; } bool ScreenSessionManager::ScreenIdManager::HasRsScreenId(ScreenId smsScreenId) const { std::shared_lock lock(screenIdMapMutex_); return rs2SmsScreenIdMap_.find(smsScreenId) != rs2SmsScreenIdMap_.end(); } sptr ScreenSessionManager::InitVirtualScreen(ScreenId smsScreenId, ScreenId rsId, VirtualScreenOption option) { TLOGI(WmsLogTag::DMS, "InitVirtualScreen: Enter"); ScreenSessionConfig config = { .screenId = smsScreenId, .rsId = rsId, .defaultScreenId = GetDefaultScreenId(), .name = option.name_, }; sptr screenSession = new(std::nothrow) ScreenSession(config, ScreenSessionReason::CREATE_SESSION_WITHOUT_DISPLAY_NODE); sptr info = new(std::nothrow) SupportedScreenModes(); if (screenSession == nullptr || info == nullptr) { TLOGI(WmsLogTag::DMS, "InitVirtualScreen: new screenSession or info failed"); screenIdManager_.DeleteScreenId(smsScreenId); rsInterface_.RemoveVirtualScreen(rsId); return nullptr; } info->width_ = option.width_; info->height_ = option.height_; auto defaultScreen = GetScreenSession(GetDefaultScreenId()); if (defaultScreen != nullptr && defaultScreen->GetActiveScreenMode() != nullptr) { info->refreshRate_ = defaultScreen->GetActiveScreenMode()->refreshRate_; } screenSession->modes_.emplace_back(info); screenSession->activeIdx_ = 0; screenSession->SetScreenType(ScreenType::VIRTUAL); screenSession->SetVirtualPixelRatio(option.density_); screenSession->SetDisplayBoundary(RectF(0, 0, option.width_, option.height_), 0); screenSession->RegisterScreenChangeListener(this); return screenSession; } bool ScreenSessionManager::InitAbstractScreenModesInfo(sptr& screenSession) { TLOGI(WmsLogTag::DMS, "Call rsInterface_ GetScreenSupportedModes"); std::vector allModes = rsInterface_.GetScreenSupportedModes( screenIdManager_.ConvertToRsScreenId(screenSession->screenId_)); if (allModes.size() == 0) { TLOGE(WmsLogTag::DMS, "allModes.size() == 0, screenId=%{public}" PRIu64"", screenSession->rsId_); return false; } for (const RSScreenModeInfo& rsScreenModeInfo : allModes) { sptr info = new(std::nothrow) SupportedScreenModes(); if (info == nullptr) { TLOGE(WmsLogTag::DMS, "create SupportedScreenModes failed"); return false; } info->id_ = static_cast(rsScreenModeInfo.GetScreenModeId()); info->width_ = static_cast(rsScreenModeInfo.GetScreenWidth()); info->height_ = static_cast(rsScreenModeInfo.GetScreenHeight()); info->refreshRate_ = rsScreenModeInfo.GetScreenRefreshRate(); screenSession->modes_.push_back(info); TLOGI(WmsLogTag::DMS, "fill screen idx:%{public}d w/h:%{public}d/%{public}d", rsScreenModeInfo.GetScreenModeId(), info->width_, info->height_); } TLOGI(WmsLogTag::DMS, "Call rsInterface_ GetScreenActiveMode"); int32_t activeModeId = rsInterface_.GetScreenActiveMode(screenSession->rsId_).GetScreenModeId(); TLOGI(WmsLogTag::DMS, "fill screen activeModeId:%{public}d", activeModeId); if (static_cast(activeModeId) >= allModes.size()) { TLOGE(WmsLogTag::DMS, "activeModeId exceed, screenId=%{public}" PRIu64", activeModeId:%{public}d/%{public}ud", screenSession->rsId_, activeModeId, static_cast(allModes.size())); return false; } screenSession->activeIdx_ = activeModeId; return true; } sptr ScreenSessionManager::InitAndGetScreen(ScreenId rsScreenId) { std::lock_guard lock(screenSessionMapMutex_); ScreenId smsScreenId = screenIdManager_.CreateAndGetNewScreenId(rsScreenId); RSScreenCapability screenCapability = rsInterface_.GetScreenCapability(rsScreenId); TLOGI(WmsLogTag::DMS, "Screen name is %{public}s, phyWidth is %{public}u, phyHeight is %{public}u", screenCapability.GetName().c_str(), screenCapability.GetPhyWidth(), screenCapability.GetPhyHeight()); ScreenSessionConfig config = { .screenId = smsScreenId, .rsId = rsScreenId, .defaultScreenId = GetDefaultScreenId(), .name = screenCapability.GetName(), }; sptr screenSession = new(std::nothrow) ScreenSession(config, ScreenSessionReason::CREATE_SESSION_FOR_VIRTUAL); if (screenSession == nullptr) { TLOGE(WmsLogTag::DMS, "InitAndGetScreen: screenSession == nullptr."); screenIdManager_.DeleteScreenId(smsScreenId); return nullptr; } if (!InitAbstractScreenModesInfo(screenSession)) { screenIdManager_.DeleteScreenId(smsScreenId); TLOGE(WmsLogTag::DMS, "InitAndGetScreen: InitAndGetScreen failed."); return nullptr; } TLOGI(WmsLogTag::DMS, "InitAndGetScreen: screenSessionMap_ add screenId=%{public}" PRIu64"", smsScreenId); screenSessionMap_.insert(std::make_pair(smsScreenId, screenSession)); return screenSession; } sptr ScreenSessionManager::AddToGroupLocked(sptr newScreen, bool isUnique) { std::lock_guard lock(screenSessionMapMutex_); sptr res; if (smsScreenGroupMap_.empty()) { TLOGI(WmsLogTag::DMS, "connect the first screen"); res = AddAsFirstScreenLocked(newScreen, isUnique); } else { res = AddAsSuccedentScreenLocked(newScreen); } return res; } sptr ScreenSessionManager::AddAsFirstScreenLocked(sptr newScreen, bool isUnique) { ScreenId smsGroupScreenId(1); std::ostringstream buffer; buffer << "ScreenGroup_" << smsGroupScreenId; std::string name = buffer.str(); // default ScreenCombination is mirror isExpandCombination_ = system::GetParameter("persist.display.expand.enabled", "0") == "1"; sptr screenGroup; if (isExpandCombination_) { screenGroup = new(std::nothrow) ScreenSessionGroup(smsGroupScreenId, SCREEN_ID_INVALID, name, ScreenCombination::SCREEN_EXPAND); newScreen->SetScreenCombination(ScreenCombination::SCREEN_EXPAND); } else if (isUnique) { screenGroup = new(std::nothrow) ScreenSessionGroup(smsGroupScreenId, SCREEN_ID_INVALID, name, ScreenCombination::SCREEN_UNIQUE); newScreen->SetScreenCombination(ScreenCombination::SCREEN_UNIQUE); } else { screenGroup = new(std::nothrow) ScreenSessionGroup(smsGroupScreenId, SCREEN_ID_INVALID, name, ScreenCombination::SCREEN_MIRROR); newScreen->SetScreenCombination(ScreenCombination::SCREEN_MIRROR); } if (screenGroup == nullptr) { TLOGE(WmsLogTag::DMS, "new ScreenSessionGroup failed"); screenIdManager_.DeleteScreenId(smsGroupScreenId); return nullptr; } screenGroup->groupSmsId_ = 1; Point point; if (!screenGroup->AddChild(newScreen, point, GetScreenSession(GetDefaultScreenId()))) { TLOGE(WmsLogTag::DMS, "fail to add screen to group. screen=%{public}" PRIu64"", newScreen->screenId_); screenIdManager_.DeleteScreenId(smsGroupScreenId); return nullptr; } std::lock_guard lock(screenSessionMapMutex_); auto iter = smsScreenGroupMap_.find(smsGroupScreenId); if (iter != smsScreenGroupMap_.end()) { TLOGE(WmsLogTag::DMS, "group screen existed. id=%{public}" PRIu64"", smsGroupScreenId); smsScreenGroupMap_.erase(iter); } smsScreenGroupMap_.insert(std::make_pair(smsGroupScreenId, screenGroup)); screenGroup->mirrorScreenId_ = newScreen->screenId_; TLOGI(WmsLogTag::DMS, "connect new group screen, screenId: %{public}" PRIu64", screenGroupId: %{public}" PRIu64", " "combination:%{public}u", newScreen->screenId_, smsGroupScreenId, newScreen->GetScreenProperty().GetScreenType()); return screenGroup; } sptr ScreenSessionManager::AddAsSuccedentScreenLocked(sptr newScreen) { ScreenId defaultScreenId = GetDefaultScreenId(); std::lock_guard lock(screenSessionMapMutex_); auto iter = screenSessionMap_.find(defaultScreenId); if (iter == screenSessionMap_.end()) { TLOGE(WmsLogTag::DMS, "defaultScreenId:%{public}" PRIu64" is not in screenSessionMap_.", defaultScreenId); return nullptr; } auto screen = iter->second; auto screenGroupIter = smsScreenGroupMap_.find(screen->groupSmsId_); if (screenGroupIter == smsScreenGroupMap_.end()) { TLOGE(WmsLogTag::DMS, "groupSmsId:%{public}" PRIu64" is not in smsScreenGroupMap_.", screen->groupSmsId_); return nullptr; } auto screenGroup = screenGroupIter->second; Point point; if (screenGroup->combination_ == ScreenCombination::SCREEN_EXPAND) { point = {screen->GetActiveScreenMode()->width_, 0}; } screenGroup->AddChild(newScreen, point, screen); return screenGroup; } sptr ScreenSessionManager::RemoveFromGroupLocked(sptr screen) { TLOGI(WmsLogTag::DMS, "RemoveFromGroupLocked."); auto groupSmsId = screen->groupSmsId_; sptr screenGroup = GetAbstractScreenGroup(groupSmsId); if (!screenGroup) { TLOGE(WmsLogTag::DMS, "groupSmsId:%{public}" PRIu64"is not in smsScreenGroupMap_.", groupSmsId); return nullptr; } if (!RemoveChildFromGroup(screen, screenGroup)) { return nullptr; } return screenGroup; } bool ScreenSessionManager::RemoveChildFromGroup(sptr screen, sptr screenGroup) { bool res = screenGroup->RemoveChild(screen); auto transactionProxy = RSTransactionProxy::GetInstance(); if (transactionProxy != nullptr) { transactionProxy->FlushImplicitTransaction(); TLOGI(WmsLogTag::DMS, "remove child and call flush."); } if (!res) { TLOGE(WmsLogTag::DMS, "remove screen:%{public}" PRIu64" failed from screenGroup:%{public}" PRIu64".", screen->screenId_, screen->groupSmsId_); return false; } if (screenGroup->GetChildCount() == 0) { // Group removed, need to do something. std::lock_guard lock(screenSessionMapMutex_); smsScreenGroupMap_.erase(screenGroup->screenId_); screenSessionMap_.erase(screenGroup->screenId_); TLOGE(WmsLogTag::DMS, "screenSessionMap_ remove screen:%{public}" PRIu64, screenGroup->screenId_); } return true; } DMError ScreenSessionManager::SetMirror(ScreenId screenId, std::vector screens) { TLOGI(WmsLogTag::DMS, "SetMirror, screenId:%{public}" PRIu64"", screenId); sptr screen = GetScreenSession(screenId); if (screen == nullptr || screen->GetScreenProperty().GetScreenType() != ScreenType::REAL) { TLOGE(WmsLogTag::DMS, "SetMirror screen is nullptr, or screenType is not real."); return DMError::DM_ERROR_NULLPTR; } screen->groupSmsId_ = 1; auto group = GetAbstractScreenGroup(screen->groupSmsId_); if (group == nullptr) { group = AddToGroupLocked(screen); if (group == nullptr) { TLOGE(WmsLogTag::DMS, "SetMirror group is nullptr"); return DMError::DM_ERROR_NULLPTR; } NotifyScreenGroupChanged(screen->ConvertToScreenInfo(), ScreenGroupChangeEvent::ADD_TO_GROUP); } Point point; std::vector startPoints; startPoints.insert(startPoints.begin(), screens.size(), point); bool filterMirroredScreen = group->combination_ == ScreenCombination::SCREEN_MIRROR && group->mirrorScreenId_ == screen->screenId_; group->mirrorScreenId_ = screen->screenId_; ChangeScreenGroup(group, screens, startPoints, filterMirroredScreen, ScreenCombination::SCREEN_MIRROR); TLOGI(WmsLogTag::DMS, "SetMirror success"); return DMError::DM_OK; } sptr ScreenSessionManager::GetAbstractScreenGroup(ScreenId smsScreenId) { std::lock_guard lock(screenSessionMapMutex_); auto iter = smsScreenGroupMap_.find(smsScreenId); if (iter == smsScreenGroupMap_.end()) { TLOGE(WmsLogTag::DMS, "did not find screen:%{public}" PRIu64"", smsScreenId); return nullptr; } return iter->second; } bool ScreenSessionManager::CheckScreenInScreenGroup(sptr screen) const { std::lock_guard lock(screenSessionMapMutex_); auto groupSmsId = screen->groupSmsId_; auto iter = smsScreenGroupMap_.find(groupSmsId); if (iter == smsScreenGroupMap_.end()) { TLOGE(WmsLogTag::DMS, "groupSmsId:%{public}" PRIu64"is not in smsScreenGroupMap_.", groupSmsId); return false; } sptr screenGroup = iter->second; return screenGroup->HasChild(screen->screenId_); } void ScreenSessionManager::ChangeScreenGroup(sptr group, const std::vector& screens, const std::vector& startPoints, bool filterScreen, ScreenCombination combination) { std::map removeChildResMap; std::vector addScreens; std::vector addChildPos; for (uint64_t i = 0; i != screens.size(); i++) { ScreenId screenId = screens[i]; TLOGI(WmsLogTag::DMS, "ChangeScreenGroup ScreenId: %{public}" PRIu64"", screenId); auto screen = GetScreenSession(screenId); if (screen == nullptr) { TLOGE(WmsLogTag::DMS, "ChangeScreenGroup screen:%{public}" PRIu64" is nullptr", screenId); continue; } TLOGI(WmsLogTag::DMS, "ChangeScreenGroup Screen->groupSmsId_: %{public}" PRIu64"", screen->groupSmsId_); screen->groupSmsId_ = 1; if (filterScreen && screen->groupSmsId_ == group->screenId_ && group->HasChild(screen->screenId_)) { continue; } if (CheckScreenInScreenGroup(screen)) { NotifyDisplayDestroy(screenId); } auto originGroup = RemoveFromGroupLocked(screen); addChildPos.emplace_back(startPoints[i]); removeChildResMap[screenId] = originGroup != nullptr; addScreens.emplace_back(screenId); } group->combination_ = combination; AddScreenToGroup(group, addScreens, addChildPos, removeChildResMap); } void ScreenSessionManager::AddScreenToGroup(sptr group, const std::vector& addScreens, const std::vector& addChildPos, std::map& removeChildResMap) { std::vector> addToGroup; std::vector> removeFromGroup; std::vector> changeGroup; for (uint64_t i = 0; i != addScreens.size(); i++) { ScreenId screenId = addScreens[i]; sptr screen = GetScreenSession(screenId); if (screen == nullptr) { continue; } Point expandPoint = addChildPos[i]; TLOGI(WmsLogTag::DMS, "AddScreenToGroup screenId: %{public}" PRIu64", Point: %{public}d, %{public}d", screen->screenId_, expandPoint.posX_, expandPoint.posY_); bool addChildRes = group->AddChild(screen, expandPoint, GetScreenSession(GetDefaultScreenId())); if (removeChildResMap[screenId] && addChildRes) { changeGroup.emplace_back(screen->ConvertToScreenInfo()); TLOGD(WmsLogTag::DMS, "changeGroup"); } else if (removeChildResMap[screenId]) { TLOGD(WmsLogTag::DMS, "removeChild"); removeFromGroup.emplace_back(screen->ConvertToScreenInfo()); } else if (addChildRes) { TLOGD(WmsLogTag::DMS, "AddChild"); addToGroup.emplace_back(screen->ConvertToScreenInfo()); } else { TLOGD(WmsLogTag::DMS, "default, AddChild failed"); } NotifyDisplayCreate(screen->ConvertToDisplayInfo()); } NotifyScreenGroupChanged(removeFromGroup, ScreenGroupChangeEvent::REMOVE_FROM_GROUP); NotifyScreenGroupChanged(changeGroup, ScreenGroupChangeEvent::CHANGE_GROUP); NotifyScreenGroupChanged(addToGroup, ScreenGroupChangeEvent::ADD_TO_GROUP); } void ScreenSessionManager::RemoveVirtualScreenFromGroup(std::vector screens) { TLOGI(WmsLogTag::DMS, "RemoveVirtualScreenFromGroup enter!"); if (!SessionPermission::IsSystemCalling()) { TLOGE(WmsLogTag::DMS, "permission denied calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return; } if (screens.empty()) { return; } std::vector> removeFromGroup; for (ScreenId screenId : screens) { auto screen = GetScreenSession(screenId); if (screen == nullptr || screen->GetScreenProperty().GetScreenType() != ScreenType::VIRTUAL) { continue; } auto originGroup = GetAbstractScreenGroup(screen->groupSmsId_); if (originGroup == nullptr) { continue; } if (!originGroup->HasChild(screenId)) { continue; } RemoveFromGroupLocked(screen); removeFromGroup.emplace_back(screen->ConvertToScreenInfo()); } NotifyScreenGroupChanged(removeFromGroup, ScreenGroupChangeEvent::REMOVE_FROM_GROUP); } const std::shared_ptr ScreenSessionManager::GetRSDisplayNodeByScreenId(ScreenId smsScreenId) const { static std::shared_ptr notFound = nullptr; sptr screen = GetScreenSession(smsScreenId); if (screen == nullptr) { TLOGE(WmsLogTag::DMS, "GetRSDisplayNodeByScreenId screen == nullptr!"); return notFound; } if (screen->GetDisplayNode() == nullptr) { TLOGE(WmsLogTag::DMS, "GetRSDisplayNodeByScreenId displayNode_ == nullptr!"); return notFound; } TLOGI(WmsLogTag::DMS, "GetRSDisplayNodeByScreenId: screen: %{public}" PRIu64", nodeId: %{public}" PRIu64" ", screen->screenId_, screen->GetDisplayNode()->GetId()); return screen->GetDisplayNode(); } std::shared_ptr ScreenSessionManager::GetScreenSnapshot(DisplayId displayId, bool isUseDma) { ScreenId screenId = SCREEN_ID_INVALID; std::shared_ptr displayNode = nullptr; { std::lock_guard lock(screenSessionMapMutex_); for (auto sessionIt : screenSessionMap_) { auto screenSession = sessionIt.second; if (screenSession == nullptr) { TLOGE(WmsLogTag::DMS, "GetScreenSnapshot screenSession is nullptr!"); continue; } sptr displayInfo = screenSession->ConvertToDisplayInfo(); if (displayInfo == nullptr) { TLOGE(WmsLogTag::DMS, "GetScreenSnapshot displayInfo is nullptr!"); continue; } TLOGI(WmsLogTag::DMS, "GetScreenSnapshot: displayId %{public}" PRIu64"", displayInfo->GetDisplayId()); if (displayId == displayInfo->GetDisplayId()) { displayNode = screenSession->GetDisplayNode(); screenId = sessionIt.first; break; } } } if (screenId == SCREEN_ID_INVALID || displayNode == nullptr) { TLOGE(WmsLogTag::DMS, "screenId is invalid or displayNode is null!"); return nullptr; } std::shared_ptr callback = std::make_shared(); RSSurfaceCaptureConfig config; config.useDma = isUseDma; TLOGW(WmsLogTag::DMS, "take surface capture with dma=%{public}d", isUseDma); bool ret = rsInterface_.TakeSurfaceCapture(displayNode, callback, config); if (!ret) { TLOGE(WmsLogTag::DMS, "GetScreenSnapshot TakeSurfaceCapture failed"); return nullptr; } std::shared_ptr screenshot = callback->GetResult(2000); // wait for <= 2000ms if (screenshot == nullptr) { TLOGE(WmsLogTag::DMS, "Failed to get pixelmap from RS, return nullptr!"); } else { TLOGI(WmsLogTag::DMS, "Sucess to get pixelmap from RS!"); } // notify dm listener sptr snapshotInfo = new ScreenshotInfo(); snapshotInfo->SetTrigger(SysCapUtil::GetClientName()); snapshotInfo->SetDisplayId(displayId); OnScreenshot(snapshotInfo); return screenshot; } std::shared_ptr ScreenSessionManager::GetDisplaySnapshot(DisplayId displayId, DmErrorCode* errorCode, bool isUseDma) { TLOGD(WmsLogTag::DMS, "ENTER!"); if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsShellCall() && errorCode) { *errorCode = DmErrorCode::DM_ERROR_NOT_SYSTEM_APP; return nullptr; } if (system::GetBoolParameter("persist.edm.disallow_screenshot", false)) { TLOGI(WmsLogTag::DMS, "GetDisplaySnapshot was disabled by edm!"); return nullptr; } if ((Permission::IsSystemCalling() && Permission::CheckCallingPermission(SCREEN_CAPTURE_PERMISSION)) || SessionPermission::IsShellCall()) { HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "ssm:GetDisplaySnapshot(%" PRIu64")", displayId); auto res = GetScreenSnapshot(displayId, isUseDma); if (res != nullptr) { NotifyScreenshot(displayId); if (SessionPermission::IsBetaVersion()) { CheckAndSendHiSysEvent("GET_DISPLAY_SNAPSHOT", "hmos.screenshot"); } } isScreenShot_ = true; NotifyCaptureStatusChanged(); return res; } else if (errorCode) { *errorCode = DmErrorCode::DM_ERROR_NO_PERMISSION; } return nullptr; } std::shared_ptr ScreenSessionManager::GetDisplaySnapshotWithOption(const CaptureOption& option, DmErrorCode* errorCode) { TLOGD(WmsLogTag::DMS, "enter!"); if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsShellCall() && errorCode) { *errorCode = DmErrorCode::DM_ERROR_NOT_SYSTEM_APP; return nullptr; } if (system::GetBoolParameter("persist.edm.disallow_screenshot", false)) { TLOGI(WmsLogTag::DMS, "snapshot was disabled by edm!"); return nullptr; } if ((Permission::IsSystemCalling() && Permission::CheckCallingPermission(SCREEN_CAPTURE_PERMISSION)) || SessionPermission::IsShellCall()) { HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "ssm:GetDisplaySnapshot(%" PRIu64")", option.displayId_); auto res = GetScreenSnapshot(option.displayId_, true); if (res != nullptr) { if (SessionPermission::IsBetaVersion()) { CheckAndSendHiSysEvent("GET_DISPLAY_SNAPSHOT", "hmos.screenshot"); } TLOGI(WmsLogTag::DMS, "isNeedNotify_:%{public}d", option.isNeedNotify_); if (option.isNeedNotify_) { isScreenShot_ = true; NotifyScreenshot(option.displayId_); NotifyCaptureStatusChanged(); } } return res; } else if (errorCode) { *errorCode = DmErrorCode::DM_ERROR_NO_PERMISSION; } return nullptr; } std::shared_ptr ScreenSessionManager::GetSnapshotByPicker(Media::Rect &rect, DmErrorCode* errorCode) { TLOGD(WmsLogTag::DMS, "ENTER!"); *errorCode = DmErrorCode::DM_ERROR_SYSTEM_INNORMAL; std::lock_guard lock(snapBypickerMutex_); if (system::GetBoolParameter("persist.edm.disallow_screenshot", false)) { *errorCode = DmErrorCode::DM_ERROR_NO_PERMISSION; TLOGI(WmsLogTag::DMS, "snapshot was disabled by edm!"); return nullptr; } ScreenId screenId = SCREEN_ID_INVALID; // get snapshot area frome Screenshot extension if (!GetSnapshotArea(rect, errorCode, screenId)) { return nullptr; } auto screenSession = GetScreenSession(screenId); if (screenSession == nullptr) { TLOGE(WmsLogTag::DMS, "can not get screen session"); return nullptr; } sptr displayInfo = screenSession->ConvertToDisplayInfo(); if (displayInfo == nullptr) { TLOGE(WmsLogTag::DMS, "can not get default display"); return nullptr; } DisplayId displayId = displayInfo->GetDisplayId(); HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "ssm:GetSnapshotByPicker(%" PRIu64")", displayId); auto pixelMap = GetScreenSnapshot(displayId, false); if (pixelMap != nullptr && SessionPermission::IsBetaVersion()) { CheckAndSendHiSysEvent("GET_DISPLAY_SNAPSHOT", "hmos.screenshot"); } isScreenShot_ = true; NotifyCaptureStatusChanged(); *errorCode = DmErrorCode::DM_OK; return pixelMap; } bool ScreenSessionManager::GetSnapshotArea(Media::Rect &rect, DmErrorCode* errorCode, ScreenId &screenId) { ConfigureScreenSnapshotParams(); if (ScreenSnapshotPickerConnection::GetInstance().SnapshotPickerConnectExtension()) { int32_t ret = ScreenSnapshotPickerConnection::GetInstance().GetScreenSnapshotInfo(rect, screenId); if (ret != 0) { TLOGE(WmsLogTag::DMS, "GetScreenSnapshotInfo failed"); ScreenSnapshotPickerConnection::GetInstance().SnapshotPickerDisconnectExtension(); if (ret == RES_FAILURE_FOR_PRIVACY_WINDOW) { *errorCode = DmErrorCode::DM_ERROR_INVALID_CALLING; } else { *errorCode = DmErrorCode::DM_ERROR_DEVICE_NOT_SUPPORT; } return false; } ScreenSnapshotPickerConnection::GetInstance().SnapshotPickerDisconnectExtension(); } else { *errorCode = DmErrorCode::DM_ERROR_DEVICE_NOT_SUPPORT; TLOGE(WmsLogTag::DMS, "SnapshotPickerConnectExtension failed"); return false; } return true; } bool ScreenSessionManager::OnRemoteDied(const sptr& agent) { if (agent == nullptr) { return false; } auto agentIter = screenAgentMap_.find(agent); if (agentIter != screenAgentMap_.end()) { while (screenAgentMap_[agent].size() > 0) { auto diedId = screenAgentMap_[agent][0]; TLOGI(WmsLogTag::DMS, "destroy screenId in OnRemoteDied: %{public}" PRIu64"", diedId); DMError res = DestroyVirtualScreen(diedId); if (res != DMError::DM_OK) { TLOGE(WmsLogTag::DMS, "destroy failed in OnRemoteDied: %{public}" PRIu64"", diedId); } } screenAgentMap_.erase(agent); } return true; } std::vector ScreenSessionManager::GetAllValidScreenIds(const std::vector& screenIds) const { std::vector validScreenIds; for (ScreenId screenId : screenIds) { auto screenIdIter = std::find(validScreenIds.begin(), validScreenIds.end(), screenId); if (screenIdIter != validScreenIds.end()) { continue; } std::lock_guard lock(screenSessionMapMutex_); auto iter = screenSessionMap_.find(screenId); if (iter != screenSessionMap_.end() && iter->second != nullptr && iter->second->GetScreenProperty().GetScreenType() != ScreenType::UNDEFINED) { validScreenIds.emplace_back(screenId); } } return validScreenIds; } sptr ScreenSessionManager::GetScreenGroupInfoById(ScreenId screenId) { if (!SessionPermission::IsSystemCalling()) { TLOGE(WmsLogTag::DMS, "Permission Denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return nullptr; } auto screenSessionGroup = GetAbstractScreenGroup(screenId); if (screenSessionGroup == nullptr) { TLOGE(WmsLogTag::DMS, "GetScreenGroupInfoById cannot find screenGroupInfo: %{public}" PRIu64"", screenId); return nullptr; } return screenSessionGroup->ConvertToScreenGroupInfo(); } void ScreenSessionManager::NotifyScreenConnected(sptr screenInfo) { if (screenInfo == nullptr) { TLOGE(WmsLogTag::DMS, "NotifyScreenConnected error, screenInfo is nullptr."); return; } auto task = [=] { TLOGI(WmsLogTag::DMS, "NotifyScreenConnected, screenId:%{public}" PRIu64"", screenInfo->GetScreenId()); OnScreenConnect(screenInfo); }; taskScheduler_->PostAsyncTask(task, "NotifyScreenConnected"); } void ScreenSessionManager::NotifyScreenDisconnected(ScreenId screenId) { auto task = [=] { TLOGI(WmsLogTag::DMS, "NotifyScreenDisconnected, screenId:%{public}" PRIu64"", screenId); OnScreenDisconnect(screenId); }; taskScheduler_->PostAsyncTask(task, "NotifyScreenDisconnected"); } void ScreenSessionManager::NotifyDisplayCreate(sptr displayInfo) { if (displayInfo == nullptr) { return; } auto agents = dmAgentContainer_.GetAgentsByType(DisplayManagerAgentType::DISPLAY_EVENT_LISTENER); if (agents.empty()) { return; } TLOGI(WmsLogTag::DMS, "NotifyDisplayCreate"); for (auto& agent : agents) { int32_t agentPid = dmAgentContainer_.GetAgentPid(agent); if (!IsFreezed(agentPid, DisplayManagerAgentType::DISPLAY_EVENT_LISTENER)) { agent->OnDisplayCreate(displayInfo); } } } void ScreenSessionManager::NotifyDisplayDestroy(DisplayId displayId) { auto agents = dmAgentContainer_.GetAgentsByType(DisplayManagerAgentType::DISPLAY_EVENT_LISTENER); if (agents.empty()) { return; } TLOGI(WmsLogTag::DMS, "NotifyDisplayDestroy"); for (auto& agent : agents) { int32_t agentPid = dmAgentContainer_.GetAgentPid(agent); if (!IsFreezed(agentPid, DisplayManagerAgentType::DISPLAY_EVENT_LISTENER)) { agent->OnDisplayDestroy(displayId); } } } void ScreenSessionManager::NotifyScreenGroupChanged( const sptr& screenInfo, ScreenGroupChangeEvent event) { if (screenInfo == nullptr) { TLOGE(WmsLogTag::DMS, "screenInfo is nullptr."); return; } std::string trigger = SysCapUtil::GetClientName(); auto task = [=] { TLOGI(WmsLogTag::DMS, "screenId:%{public}" PRIu64", trigger:[%{public}s]", screenInfo->GetScreenId(), trigger.c_str()); OnScreenGroupChange(trigger, screenInfo, event); }; taskScheduler_->PostAsyncTask(task, "NotifyScreenGroupChanged:PID"); } void ScreenSessionManager::NotifyScreenGroupChanged( const std::vector>& screenInfo, ScreenGroupChangeEvent event) { if (screenInfo.empty()) { return; } std::string trigger = SysCapUtil::GetClientName(); auto task = [=] { TLOGI(WmsLogTag::DMS, "trigger:[%{public}s]", trigger.c_str()); OnScreenGroupChange(trigger, screenInfo, event); }; taskScheduler_->PostAsyncTask(task, "NotifyScreenGroupChanged"); } void ScreenSessionManager::NotifyPrivateSessionStateChanged(bool hasPrivate) { if (hasPrivate == screenPrivacyStates) { TLOGD(WmsLogTag::DMS, "screen session state is not changed, return"); return; } TLOGI(WmsLogTag::DMS, "PrivateSession status : %{public}u", hasPrivate); screenPrivacyStates = hasPrivate; auto agents = dmAgentContainer_.GetAgentsByType(DisplayManagerAgentType::PRIVATE_WINDOW_LISTENER); if (agents.empty()) { return; } for (auto& agent : agents) { agent->NotifyPrivateWindowStateChanged(hasPrivate); } } void ScreenSessionManager::SetScreenPrivacyState(bool hasPrivate) { if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "Permission Denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return; } TLOGI(WmsLogTag::DMS, "SetScreenPrivacyState enter, hasPrivate: %{public}d", hasPrivate); ScreenId id = GetDefaultScreenId(); auto screenSession = GetScreenSession(id); if (screenSession == nullptr) { TLOGE(WmsLogTag::DMS, "can not get default screen now"); return; } screenSession->SetPrivateSessionForeground(hasPrivate); NotifyPrivateSessionStateChanged(hasPrivate); } void ScreenSessionManager::SetPrivacyStateByDisplayId(DisplayId id, bool hasPrivate) { if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "Permission Denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return; } TLOGI(WmsLogTag::DMS, "SetPrivacyStateByDisplayId enter, hasPrivate: %{public}d", hasPrivate); std::vector screenIds = GetAllScreenIds(); auto iter = std::find(screenIds.begin(), screenIds.end(), id); if (iter == screenIds.end()) { TLOGE(WmsLogTag::DMS, "SetPrivacyStateByDisplayId invalid displayId"); return; } auto screenSession = GetScreenSession(id); if (screenSession == nullptr) { TLOGE(WmsLogTag::DMS, "can not get id: %{public}" PRIu64" screen now", id); return; } screenSession->SetPrivateSessionForeground(hasPrivate); NotifyPrivateSessionStateChanged(hasPrivate); } void ScreenSessionManager::SetScreenPrivacyWindowList(DisplayId id, std::vector privacyWindowList) { if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "Permmission Denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return; } TLOGI(WmsLogTag::DMS, "SetScreenPrivacyWindowList enter"); std::vector screenIds = GetAllScreenIds(); auto iter = std::find(screenIds.begin(), screenIds.end(), id); if (iter == screenIds.end()) { TLOGE(WmsLogTag::DMS, "SetScreenPrivacyWindowList invalid displayId"); return; } auto screenSession = GetScreenSession(id); if (screenSession == nullptr) { TLOGE(WmsLogTag::DMS, "can not get id: %{public}" PRIu64" screen now", id); return; } NotifyPrivateWindowListChanged(id, privacyWindowList); } void ScreenSessionManager::NotifyPrivateWindowListChanged(DisplayId id, std::vector privacyWindowList) { TLOGI(WmsLogTag::DMS, "Notify displayid: %{public}" PRIu64" PrivateWindowListChanged", id); auto agents = dmAgentContainer_.GetAgentsByType(DisplayManagerAgentType::PRIVATE_WINDOW_LIST_LISTENER); if (agents.empty()) { return; } for (auto& agent : agents) { agent->NotifyPrivateStateWindowListChanged(id, privacyWindowList); } } DMError ScreenSessionManager::HasPrivateWindow(DisplayId id, bool& hasPrivateWindow) { if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "Permmision Denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return DMError::DM_ERROR_NOT_SYSTEM_APP; } std::vector screenIds = GetAllScreenIds(); auto iter = std::find(screenIds.begin(), screenIds.end(), id); if (iter == screenIds.end()) { TLOGE(WmsLogTag::DMS, "HasPrivateWindow invalid displayId"); return DMError::DM_ERROR_INVALID_PARAM; } auto screenSession = GetScreenSession(id); if (screenSession == nullptr) { return DMError::DM_ERROR_NULLPTR; } hasPrivateWindow = screenSession->HasPrivateSessionForeground(); TLOGI(WmsLogTag::DMS, "id: %{public}" PRIu64" has private window: %{public}u", id, static_cast(hasPrivateWindow)); return DMError::DM_OK; } void ScreenSessionManager::OnScreenGroupChange(const std::string& trigger, const sptr& screenInfo, ScreenGroupChangeEvent groupEvent) { if (screenInfo == nullptr) { return; } std::vector> screenInfos; screenInfos.push_back(screenInfo); OnScreenGroupChange(trigger, screenInfos, groupEvent); } void ScreenSessionManager::OnScreenGroupChange(const std::string& trigger, const std::vector>& screenInfos, ScreenGroupChangeEvent groupEvent) { auto agents = dmAgentContainer_.GetAgentsByType(DisplayManagerAgentType::SCREEN_EVENT_LISTENER); std::vector> infos; for (auto& screenInfo : screenInfos) { if (screenInfo != nullptr) { infos.emplace_back(screenInfo); } } if (agents.empty() || infos.empty()) { return; } for (auto& agent : agents) { agent->OnScreenGroupChange(trigger, infos, groupEvent); } } void ScreenSessionManager::OnScreenConnect(const sptr screenInfo) { if (screenInfo == nullptr) { TLOGE(WmsLogTag::DMS, "OnScreenConnect screenInfo nullptr"); return; } auto agents = dmAgentContainer_.GetAgentsByType(DisplayManagerAgentType::SCREEN_EVENT_LISTENER); if (agents.empty()) { TLOGI(WmsLogTag::DMS, "OnScreenConnect agents empty"); return; } TLOGI(WmsLogTag::DMS, "OnScreenConnect"); for (auto& agent : agents) { agent->OnScreenConnect(screenInfo); } NotifyScreenModeChange(); } void ScreenSessionManager::OnScreenDisconnect(ScreenId screenId) { auto agents = dmAgentContainer_.GetAgentsByType(DisplayManagerAgentType::SCREEN_EVENT_LISTENER); if (agents.empty()) { TLOGI(WmsLogTag::DMS, "OnScreenDisconnect agents empty"); return; } TLOGI(WmsLogTag::DMS, "OnScreenDisconnect"); for (auto& agent : agents) { agent->OnScreenDisconnect(screenId); } NotifyScreenModeChange(); } void ScreenSessionManager::OnScreenshot(sptr info) { if (info == nullptr) { TLOGE(WmsLogTag::DMS, "OnScreenshot info is null"); return; } auto agents = dmAgentContainer_.GetAgentsByType(DisplayManagerAgentType::SCREENSHOT_EVENT_LISTENER); if (agents.empty()) { TLOGD(WmsLogTag::DMS, "agents empty"); return; } TLOGI(WmsLogTag::DMS, "onScreenshot"); for (auto& agent : agents) { agent->OnScreenshot(info); } } sptr ScreenSessionManager::GetCutoutInfo(DisplayId displayId) { DmsXcollie dmsXcollie("DMS:GetCutoutInfo", XCOLLIE_TIMEOUT_10S); return screenCutoutController_ ? screenCutoutController_->GetScreenCutoutInfo(displayId) : nullptr; } DMError ScreenSessionManager::HasImmersiveWindow(bool& immersive) { if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "permission denied!"); return DMError::DM_ERROR_NOT_SYSTEM_APP; } if (!clientProxy_) { TLOGI(WmsLogTag::DMS, "clientProxy_ is null"); return DMError::DM_ERROR_NULLPTR; } clientProxy_->OnImmersiveStateChanged(immersive); return DMError::DM_OK; } void ScreenSessionManager::SetDisplayBoundary(const sptr screenSession) { if (screenSession && screenCutoutController_) { RectF rect = screenCutoutController_->CalculateCurvedCompression(screenSession->GetScreenProperty()); if (!rect.IsEmpty()) { screenSession->SetDisplayBoundary(rect, screenCutoutController_->GetOffsetY()); } } else { TLOGW(WmsLogTag::DMS, "screenSession or screenCutoutController_ is null"); } } std::string ScreenSessionManager::TransferTypeToString(ScreenType type) const { std::string screenType; switch (type) { case ScreenType::REAL: screenType = "REAL"; break; case ScreenType::VIRTUAL: screenType = "VIRTUAL"; break; default: screenType = "UNDEFINED"; break; } return screenType; } std::string ScreenSessionManager::TransferPropertyChangeTypeToString(ScreenPropertyChangeType type) const { std::string screenType; switch (type) { case ScreenPropertyChangeType::UNSPECIFIED: screenType = "UNSPECIFIED"; break; case ScreenPropertyChangeType::ROTATION_BEGIN: screenType = "ROTATION_BEGIN"; break; case ScreenPropertyChangeType::ROTATION_END: screenType = "ROTATION_END"; break; default: screenType = "ROTATION_UPDATE_PROPERTY_ONLY"; break; } return screenType; } void ScreenSessionManager::DumpAllScreensInfo(std::string& dumpInfo) { if (!(SessionPermission::IsSACalling() || SessionPermission::IsStartByHdcd())) { TLOGE(WmsLogTag::DMS, "Permission Denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return; } std::ostringstream oss; oss << "--------------------------------------Free Screen" << "--------------------------------------" << std::endl; oss << "ScreenName Type IsGroup DmsId RsId ActiveIdx VPR Rotation Orientation " << "RequestOrientation NodeId " << std::endl; std::lock_guard lock(screenSessionMapMutex_); for (auto sessionIt : screenSessionMap_) { auto screenSession = sessionIt.second; if (screenSession == nullptr) { continue; } sptr screenInfo = screenSession->ConvertToScreenInfo(); if (screenInfo == nullptr) { continue; } std::string screenType = TransferTypeToString(screenInfo->GetType()); NodeId nodeId = (screenSession->GetDisplayNode() == nullptr) ? SCREEN_ID_INVALID : screenSession->GetDisplayNode()->GetId(); oss << std::left << std::setw(21) << screenInfo->GetName() // 21 is width << std::left << std::setw(9) << screenType // 9 is width << std::left << std::setw(8) << (screenSession->isScreenGroup_ ? "true" : "false") // 8 is width << std::left << std::setw(6) << screenSession->screenId_ // 6 is width << std::left << std::setw(21) << screenSession->rsId_ // 21 is width << std::left << std::setw(10) << screenSession->activeIdx_ // 10 is width << std::left << std::setw(4) << screenInfo->GetVirtualPixelRatio() // 4 is width << std::left << std::setw(9) << static_cast(screenInfo->GetRotation()) // 9 is width << std::left << std::setw(12) << static_cast(screenInfo->GetOrientation()) // 12 is width << std::left << std::setw(19) // 19 is width << static_cast(screenSession->GetScreenRequestedOrientation()) << std::left << std::setw(21) << nodeId // 21 is width << std::endl; } oss << "total screen num: " << screenSessionMap_.size() << std::endl; dumpInfo.append(oss.str()); } void ScreenSessionManager::DumpSpecialScreenInfo(ScreenId id, std::string& dumpInfo) { if (!(SessionPermission::IsSACalling() || SessionPermission::IsStartByHdcd())) { TLOGE(WmsLogTag::DMS, "Permission Denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return; } std::ostringstream oss; sptr session = GetScreenSession(id); if (!session) { TLOGE(WmsLogTag::DMS, "Get screen session failed."); oss << "This screen id is invalid."; dumpInfo.append(oss.str()); return; } sptr screenInfo = GetScreenInfoById(id); if (screenInfo == nullptr) { return; } std::string screenType = TransferTypeToString(screenInfo->GetType()); NodeId nodeId = (session->GetDisplayNode() == nullptr) ? SCREEN_ID_INVALID : session->GetDisplayNode()->GetId(); oss << "ScreenName: " << screenInfo->GetName() << std::endl; oss << "Type: " << screenType << std::endl; oss << "IsGroup: " << (session->isScreenGroup_ ? "true" : "false") << std::endl; oss << "DmsId: " << id << std::endl; oss << "RsId: " << session->rsId_ << std::endl; oss << "ActiveIdx: " << session->activeIdx_ << std::endl; oss << "VPR: " << screenInfo->GetVirtualPixelRatio() << std::endl; oss << "Rotation: " << static_cast(screenInfo->GetRotation()) << std::endl; oss << "Orientation: " << static_cast(screenInfo->GetOrientation()) << std::endl; oss << "RequestOrientation: " << static_cast(session->GetScreenRequestedOrientation()) << std::endl; oss << "NodeId: " << nodeId << std::endl; dumpInfo.append(oss.str()); } // --- Fold Screen --- ScreenProperty ScreenSessionManager::GetPhyScreenProperty(ScreenId screenId) { std::lock_guard lock_phy(phyScreenPropMapMutex_); ScreenProperty property; auto iter = phyScreenPropMap_.find(screenId); if (iter == phyScreenPropMap_.end()) { TLOGI(WmsLogTag::DMS, "Error found physic screen config with id: %{public}" PRIu64, screenId); return property; } return iter->second; } void ScreenSessionManager::SetFoldDisplayMode(const FoldDisplayMode displayMode) { if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "Permission Denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return; } if (!g_foldScreenFlag) { return; } if (foldScreenController_ == nullptr) { TLOGI(WmsLogTag::DMS, "SetFoldDisplayMode foldScreenController_ is null"); return; } if (!SessionPermission::IsSystemCalling()) { TLOGE(WmsLogTag::DMS, "SetFoldDisplayMode permission denied!"); return; } TLOGI(WmsLogTag::DMS, "calling clientName: %{public}s, calling pid: %{public}d, setmode: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid(), displayMode); if (foldScreenController_->GetTentMode() && (displayMode == FoldDisplayMode::FULL || displayMode == FoldDisplayMode::COORDINATION)) { TLOGW(WmsLogTag::DMS, "in TentMode, SetFoldDisplayMode to %{public}d failed", displayMode); return; } foldScreenController_->SetDisplayMode(displayMode); NotifyClientProxyUpdateFoldDisplayMode(displayMode); } DMError ScreenSessionManager::SetFoldDisplayModeFromJs(const FoldDisplayMode displayMode) { if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "Permission Denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return DMError::DM_ERROR_NOT_SYSTEM_APP; } SetFoldDisplayMode(displayMode); return DMError::DM_OK; } void ScreenSessionManager::UpdateDisplayScaleState(ScreenId screenId) { auto session = GetScreenSession(screenId); if (session == nullptr) { TLOGE(WmsLogTag::DMS, "session is null"); return; } const ScreenProperty& property = session->GetScreenProperty(); if (std::fabs(property.GetScaleX() - DEFAULT_SCALE) < FLT_EPSILON && std::fabs(property.GetScaleY() - DEFAULT_SCALE) < FLT_EPSILON && std::fabs(property.GetPivotX() - DEFAULT_PIVOT) < FLT_EPSILON && std::fabs(property.GetPivotY() - DEFAULT_PIVOT) < FLT_EPSILON) { TLOGD(WmsLogTag::DMS, "The scale and pivot is default value now. There is no need to update"); return; } SetDisplayScaleInner(screenId, property.GetScaleX(), property.GetScaleY(), property.GetPivotX(), property.GetPivotY()); } void ScreenSessionManager::SetDisplayScaleInner(ScreenId screenId, const float& scaleX, const float& scaleY, const float& pivotX, const float& pivotY) { auto session = GetScreenSession(screenId); if (session == nullptr) { TLOGE(WmsLogTag::DMS, "session is null"); return; } if (pivotX > 1.0f || pivotX < 0.0f || pivotY > 1.0f || pivotY < 0.0f) { TLOGE(WmsLogTag::DMS, "pivotX [%{public}f] and pivotY [%{public}f] should be in [0.0~1.0f]", pivotX, pivotY); return; } float translateX = 0.0f; float translateY = 0.0f; if (ROTATE_POLICY == FOLDABLE_DEVICE && FoldDisplayMode::FULL == GetFoldDisplayMode()) { CalcDisplayNodeTranslateOnFoldableRotation(session, scaleX, scaleY, pivotX, pivotY, translateX, translateY); } else { CalcDisplayNodeTranslateOnRotation(session, scaleX, scaleY, pivotX, pivotY, translateX, translateY); } TLOGD(WmsLogTag::DMS, "screenId %{public}" PRIu64 ", scale [%{public}f, %{public}f], " "pivot [%{public}f, %{public}f], translate [%{public}f, %{public}f]", screenId, scaleX, scaleY, pivotX, pivotY, translateX, translateY); session->SetScreenScale(scaleX, scaleY, pivotX, pivotY, translateX, translateY); NotifyDisplayStateChange(GetDefaultScreenId(), session->ConvertToDisplayInfo(), {}, DisplayStateChangeType::UPDATE_SCALE); } void ScreenSessionManager::CalcDisplayNodeTranslateOnFoldableRotation(sptr& session, const float& scaleX, const float& scaleY, const float& pivotX, const float& pivotY, float& translateX, float& translateY) { if (session == nullptr) { TLOGE(WmsLogTag::DMS, "session is nullptr"); return; } const ScreenProperty& screenProperty = session->GetScreenProperty(); auto screenWidth = screenProperty.GetBounds().rect_.GetWidth(); auto screenHeight = screenProperty.GetBounds().rect_.GetHeight(); Rotation rotation = session->GetRotation(); float rotatedPivotX = DEFAULT_PIVOT; float rotatedPivotY = DEFAULT_PIVOT; float width = 0.0f; float height = 0.0f; switch (rotation) { case Rotation::ROTATION_0: rotatedPivotX = pivotY; rotatedPivotY = 1.0f - pivotX; width = screenHeight; height = screenWidth; break; case Rotation::ROTATION_90: rotatedPivotX = 1.0f - pivotX; rotatedPivotY = 1.0f - pivotY; width = screenWidth; height = screenHeight; break; case Rotation::ROTATION_180: rotatedPivotX = 1.0f - pivotY; rotatedPivotY = pivotX; width = screenHeight; height = screenWidth; break; case Rotation::ROTATION_270: rotatedPivotX = pivotX; rotatedPivotY = pivotY; width = screenWidth; height = screenHeight; break; default: TLOGE(WmsLogTag::DMS, "Unknown Rotation %{public}d", rotation); break; } translateX = (DEFAULT_PIVOT - rotatedPivotX) * (scaleX - DEFAULT_SCALE) * width; translateY = (DEFAULT_PIVOT - rotatedPivotY) * (scaleY - DEFAULT_SCALE) * height; } void ScreenSessionManager::CalcDisplayNodeTranslateOnRotation(sptr& session, const float& scaleX, const float& scaleY, const float& pivotX, const float& pivotY, float& translateX, float& translateY) { if (session == nullptr) { TLOGE(WmsLogTag::DMS, "session is nullptr"); return; } const ScreenProperty& screenProperty = session->GetScreenProperty(); auto screenWidth = screenProperty.GetBounds().rect_.GetWidth(); auto screenHeight = screenProperty.GetBounds().rect_.GetHeight(); Rotation rotation = session->GetRotation(); float rotatedPivotX = DEFAULT_PIVOT; float rotatedPivotY = DEFAULT_PIVOT; float width = 0.0f; float height = 0.0f; switch (rotation) { case Rotation::ROTATION_0: rotatedPivotX = pivotX; rotatedPivotY = pivotY; width = screenWidth; height = screenHeight; break; case Rotation::ROTATION_90: rotatedPivotX = pivotY; rotatedPivotY = 1.0f - pivotX; width = screenHeight; height = screenWidth; break; case Rotation::ROTATION_180: rotatedPivotX = 1.0f - pivotX; rotatedPivotY = 1.0f - pivotY; width = screenWidth; height = screenHeight; break; case Rotation::ROTATION_270: rotatedPivotX = 1.0f - pivotY; rotatedPivotY = pivotX; width = screenHeight; height = screenWidth; break; default: TLOGE(WmsLogTag::DMS, "Unknown Rotation %{public}d", rotation); break; } translateX = (DEFAULT_PIVOT - rotatedPivotX) * (scaleX - DEFAULT_SCALE) * width; translateY = (DEFAULT_PIVOT - rotatedPivotY) * (scaleY - DEFAULT_SCALE) * height; } void ScreenSessionManager::SetDisplayScale(ScreenId screenId, float scaleX, float scaleY, float pivotX, float pivotY) { if (!SessionPermission::IsSACalling()) { TLOGE(WmsLogTag::DMS, "calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return; } SetDisplayScaleInner(screenId, scaleX, scaleY, pivotX, pivotY); } void ScreenSessionManager::SetFoldStatusLocked(bool locked) { if (!g_foldScreenFlag) { return; } if (foldScreenController_ == nullptr) { TLOGI(WmsLogTag::DMS, "SetFoldStatusLocked foldScreenController_ is null"); return; } if (!SessionPermission::IsSystemCalling()) { TLOGE(WmsLogTag::DMS, "Permission Denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return; } foldScreenController_->LockDisplayStatus(locked); } DMError ScreenSessionManager::SetFoldStatusLockedFromJs(bool locked) { if (!SessionPermission::IsSystemCalling()) { TLOGE(WmsLogTag::DMS, "Permission Denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return DMError::DM_ERROR_NOT_SYSTEM_APP; } SetFoldStatusLocked(locked); return DMError::DM_OK; } FoldDisplayMode ScreenSessionManager::GetFoldDisplayMode() { DmsXcollie dmsXcollie("DMS:GetFoldDisplayMode", XCOLLIE_TIMEOUT_10S); if (!g_foldScreenFlag) { return FoldDisplayMode::UNKNOWN; } if (foldScreenController_ == nullptr) { TLOGD(WmsLogTag::DMS, "GetFoldDisplayMode foldScreenController_ is null"); return FoldDisplayMode::UNKNOWN; } return foldScreenController_->GetDisplayMode(); } bool ScreenSessionManager::IsFoldable() { DmsXcollie dmsXcollie("DMS:IsFoldable", XCOLLIE_TIMEOUT_10S); // Most applications do not adapt to Lem rotation and are temporarily treated as non fold device if (FoldScreenStateInternel::IsDualDisplayFoldDevice()) { return false; } if (!g_foldScreenFlag) { return false; } if (foldScreenController_ == nullptr) { TLOGI(WmsLogTag::DMS, "foldScreenController_ is null"); return false; } return foldScreenController_->IsFoldable(); } bool ScreenSessionManager::IsCaptured() { return isScreenShot_ || virtualScreenCount_ > 0 || hdmiScreenCount_ > 0; } bool ScreenSessionManager::IsMultiScreenCollaboration() { return isMultiScreenCollaboration_; } FoldStatus ScreenSessionManager::GetFoldStatus() { DmsXcollie dmsXcollie("DMS:GetFoldStatus", XCOLLIE_TIMEOUT_10S); if (!g_foldScreenFlag) { return FoldStatus::UNKNOWN; } if (foldScreenController_ == nullptr) { TLOGI(WmsLogTag::DMS, "foldScreenController_ is null"); return FoldStatus::UNKNOWN; } return foldScreenController_->GetFoldStatus(); } bool ScreenSessionManager::GetTentMode() { if (!g_foldScreenFlag) { return false; } if (foldScreenController_ == nullptr) { TLOGI(WmsLogTag::DMS, "foldScreenController_ is null"); return false; } return foldScreenController_->GetTentMode(); } sptr ScreenSessionManager::GetCurrentFoldCreaseRegion() { if (!g_foldScreenFlag) { return nullptr; } if (foldScreenController_ == nullptr) { TLOGI(WmsLogTag::DMS, "foldScreenController_ is null"); return nullptr; } return foldScreenController_->GetCurrentFoldCreaseRegion(); } uint32_t ScreenSessionManager::GetCurvedCompressionArea() { return ScreenSceneConfig::GetCurvedCompressionAreaInLandscape(); } void ScreenSessionManager::NotifyFoldStatusChanged(FoldStatus foldStatus) { TLOGI(WmsLogTag::DMS, "NotifyFoldStatusChanged foldStatus:%{public}d", foldStatus); sptr screenSession = GetDefaultScreenSession(); if (screenSession != nullptr) { if (foldStatus == FoldStatus::FOLDED) { screenSession->SetDefaultDeviceRotationOffset(0); } else { screenSession->SetDefaultDeviceRotationOffset(defaultDeviceRotationOffset_); } } if (screenSession != nullptr && FoldScreenStateInternel::IsSingleDisplayPocketFoldDevice()) { // 维护外屏独立dpi if (foldStatus == FoldStatus::FOLDED) { auto property = screenSession->GetScreenProperty(); densityDpi_ = property.GetDensity(); SetVirtualPixelRatio(GetDefaultScreenId(), subDensityDpi_); } else { SetVirtualPixelRatio(GetDefaultScreenId(), densityDpi_); } } auto agents = dmAgentContainer_.GetAgentsByType(DisplayManagerAgentType::FOLD_STATUS_CHANGED_LISTENER); if (agents.empty()) { TLOGI(WmsLogTag::DMS, "NotifyFoldStatusChanged agents is empty"); return; } for (auto& agent : agents) { int32_t agentPid = dmAgentContainer_.GetAgentPid(agent); if (!IsFreezed(agentPid, DisplayManagerAgentType::FOLD_STATUS_CHANGED_LISTENER)) { agent->NotifyFoldStatusChanged(foldStatus); } } } void ScreenSessionManager::NotifyFoldAngleChanged(std::vector foldAngles) { auto agents = dmAgentContainer_.GetAgentsByType(DisplayManagerAgentType::FOLD_ANGLE_CHANGED_LISTENER); if (agents.empty()) { TLOGI(WmsLogTag::DMS, "NotifyFoldAngleChanged agents is empty"); return; } { std::lock_guard lock(lastStatusUpdateMutex_); lastFoldAngles_ = foldAngles; } for (auto& agent : agents) { int32_t agentPid = dmAgentContainer_.GetAgentPid(agent); if (!IsFreezed(agentPid, DisplayManagerAgentType::FOLD_ANGLE_CHANGED_LISTENER)) { agent->NotifyFoldAngleChanged(foldAngles); } } } void ScreenSessionManager::NotifyCaptureStatusChanged() { auto agents = dmAgentContainer_.GetAgentsByType(DisplayManagerAgentType::CAPTURE_STATUS_CHANGED_LISTENER); bool isCapture = IsCaptured(); isScreenShot_ = false; if (agents.empty()) { TLOGI(WmsLogTag::DMS, "agents is empty"); return; } for (auto& agent : agents) { int32_t agentPid = dmAgentContainer_.GetAgentPid(agent); if (!IsFreezed(agentPid, DisplayManagerAgentType::CAPTURE_STATUS_CHANGED_LISTENER)) { agent->NotifyCaptureStatusChanged(isCapture); } } } void ScreenSessionManager::NotifyDisplayChangeInfoChanged(const sptr& info) { auto agents = dmAgentContainer_.GetAgentsByType(DisplayManagerAgentType::DISPLAY_UPDATE_LISTENER); if (agents.empty()) { TLOGI(WmsLogTag::DMS, "Agents is empty"); return; } { std::lock_guard lock(lastStatusUpdateMutex_); lastDisplayChangeInfo_ = info; } for (auto& agent : agents) { int32_t agentPid = dmAgentContainer_.GetAgentPid(agent); if (!IsFreezed(agentPid, DisplayManagerAgentType::DISPLAY_UPDATE_LISTENER)) { agent->NotifyDisplayChangeInfoChanged(info); } } } void ScreenSessionManager::NotifyDisplayModeChanged(FoldDisplayMode displayMode) { TLOGI(WmsLogTag::DMS, "DisplayMode:%{public}d", displayMode); NotifyClientProxyUpdateFoldDisplayMode(displayMode); auto agents = dmAgentContainer_.GetAgentsByType(DisplayManagerAgentType::DISPLAY_MODE_CHANGED_LISTENER); if (agents.empty()) { TLOGI(WmsLogTag::DMS, "Agents is empty"); return; } for (auto& agent : agents) { int32_t agentPid = dmAgentContainer_.GetAgentPid(agent); if (!IsFreezed(agentPid, DisplayManagerAgentType::DISPLAY_MODE_CHANGED_LISTENER)) { agent->NotifyDisplayModeChanged(displayMode); } } } void ScreenSessionManager::SetDisplayNodeScreenId(ScreenId screenId, ScreenId displayNodeScreenId) { TLOGI(WmsLogTag::DMS, "screenId: %{public}" PRIu64 " displayNodeScreenId: %{public}" PRIu64, screenId, displayNodeScreenId); HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "ssm:SetDisplayNodeScreenId"); if (!clientProxy_) { TLOGI(WmsLogTag::DMS, "SetDisplayNodeScreenId clientProxy_ is null"); return; } clientProxy_->SetDisplayNodeScreenId(screenId, displayNodeScreenId); #ifdef DEVICE_STATUS_ENABLE SetDragWindowScreenId(screenId, displayNodeScreenId); #endif // DEVICE_STATUS_ENABLE } #ifdef DEVICE_STATUS_ENABLE void ScreenSessionManager::SetDragWindowScreenId(ScreenId screenId, ScreenId displayNodeScreenId) { auto interactionManager = Msdp::DeviceStatus::InteractionManager::GetInstance(); if (interactionManager != nullptr) { interactionManager->SetDragWindowScreenId(screenId, displayNodeScreenId); } } #endif // DEVICE_STATUS_ENABLE void ScreenSessionManager::OnPropertyChange(const ScreenProperty& newProperty, ScreenPropertyChangeReason reason, ScreenId screenId) { TLOGI(WmsLogTag::DMS, "screenId: %{public}" PRIu64 " reason: %{public}d", screenId, static_cast(reason)); if (!clientProxy_) { TLOGI(WmsLogTag::DMS, "OnPropertyChange clientProxy_ is null"); return; } clientProxy_->OnPropertyChanged(screenId, newProperty, reason); } void ScreenSessionManager::OnPowerStatusChange(DisplayPowerEvent event, EventStatus status, PowerStateChangeReason reason) { TLOGI(WmsLogTag::DMS, "[UL_POWER]event: %{public}d, status: %{public}d, reason: %{public}d", static_cast(event), static_cast(status), static_cast(reason)); if (!clientProxy_) { TLOGI(WmsLogTag::DMS, "[UL_POWER]OnPowerStatusChange clientProxy_ is null"); return; } clientProxy_->OnPowerStatusChanged(event, status, reason); } void ScreenSessionManager::OnSensorRotationChange(float sensorRotation, ScreenId screenId) { TLOGI(WmsLogTag::DMS, "screenId: %{public}" PRIu64 " sensorRotation: %{public}f", screenId, sensorRotation); if (!clientProxy_) { TLOGI(WmsLogTag::DMS, "OnSensorRotationChange clientProxy_ is null"); return; } clientProxy_->OnSensorRotationChanged(screenId, sensorRotation); } void ScreenSessionManager::OnHoverStatusChange(int32_t hoverStatus, ScreenId screenId) { TLOGI(WmsLogTag::DMS, "screenId: %{public}" PRIu64 " hoverStatus: %{public}d", screenId, hoverStatus); if (!clientProxy_) { TLOGI(WmsLogTag::DMS, "clientProxy_ is null"); return; } clientProxy_->OnHoverStatusChanged(screenId, hoverStatus); } void ScreenSessionManager::OnScreenOrientationChange(float screenOrientation, ScreenId screenId) { TLOGI(WmsLogTag::DMS, "screenId: %{public}" PRIu64 " screenOrientation: %{public}f", screenId, screenOrientation); if (!clientProxy_) { TLOGI(WmsLogTag::DMS, "OnScreenOrientationChange clientProxy_ is null"); return; } clientProxy_->OnScreenOrientationChanged(screenId, screenOrientation); } void ScreenSessionManager::OnScreenRotationLockedChange(bool isLocked, ScreenId screenId) { TLOGI(WmsLogTag::DMS, "screenId: %{public}" PRIu64 " isLocked: %{public}d", screenId, isLocked); if (!clientProxy_) { TLOGI(WmsLogTag::DMS, "OnScreenRotationLockedChange clientProxy_ is null"); return; } clientProxy_->OnScreenRotationLockedChanged(screenId, isLocked); } void ScreenSessionManager::NotifyClientProxyUpdateFoldDisplayMode(FoldDisplayMode displayMode) { if (clientProxy_) { TLOGI(WmsLogTag::DMS, "NotifyClientProxyUpdateFoldDisplayMode displayMode = %{public}d", static_cast(displayMode)); clientProxy_->OnUpdateFoldDisplayMode(displayMode); } } void ScreenSessionManager::BlockScbByAvailabelBuffer() { std::unique_lock lock(scbBufferAvailableMutex_); if (scbBufferAvailableCV_.wait_for(lock, std::chrono::milliseconds(CV_WAIT_BUFFER_AVAILABLE_MS)) == std::cv_status::timeout) { TLOGI(WmsLogTag::DMS, "available wait scbBufferAvailableCV_ timeout"); } } void ScreenSessionManager::ScbClientDeathCallback(int32_t deathScbPid) { std::unique_lock lock(oldScbPidsMutex_); if (deathScbPid == currentScbPId_ || currentScbPId_ == INVALID_SCB_PID) { clientProxy_ = nullptr; TLOGE(WmsLogTag::DMS, "death callback, clientProxy is set null"); } if (scbSwitchCV_.wait_for(lock, std::chrono::milliseconds(CV_WAIT_SCBSWITCH_MS)) == std::cv_status::timeout) { TLOGE(WmsLogTag::DMS, "set client task deathScbPid:%{public}d, timeout: %{public}d", deathScbPid, CV_WAIT_SCBSWITCH_MS); } std::ostringstream oss; oss << "Scb client death: " << deathScbPid; TLOGI(WmsLogTag::DMS, "%{public}s", oss.str().c_str()); screenEventTracker_.RecordEvent(oss.str()); oldScbPids_.erase(std::remove(oldScbPids_.begin(), oldScbPids_.end(), deathScbPid), oldScbPids_.end()); } void ScreenSessionManager::AddScbClientDeathRecipient(const sptr& scbClient, int32_t scbPid) { sptr scbClientDeathListener = new (std::nothrow) ScbClientListenerDeathRecipient(scbPid); if (scbClientDeathListener == nullptr) { TLOGE(WmsLogTag::DMS, "add scb: %{public}d death listener failed", scbPid); return; } if (scbClient != nullptr && scbClient->AsObject() != nullptr) { TLOGI(WmsLogTag::DMS, "add scb: %{public}d death listener", scbPid); scbClient->AsObject()->AddDeathRecipient(scbClientDeathListener); } } void ScreenSessionManager::SwitchUser() { if (!SessionPermission::IsSystemCalling()) { TLOGE(WmsLogTag::DMS, "permission denied, calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return; } auto userId = GetUserIdByCallingUid(); auto newScbPid = IPCSkeleton::GetCallingPid(); if (userId == currentUserId_) { TLOGE(WmsLogTag::DMS, "switch user not change"); return; } SwitchScbNodeHandle(userId, newScbPid, false); MockSessionManagerService::GetInstance().NotifyWMSConnected(userId, GetDefaultScreenId(), false); } void ScreenSessionManager::ScbStatusRecoveryWhenSwitchUser(std::vector oldScbPids, int32_t newScbPid) { sptr screenSession = GetDefaultScreenSession(); if (screenSession == nullptr) { TLOGE(WmsLogTag::DMS, "fail to get default screenSession"); return; } if (g_foldScreenFlag) { NotifyFoldStatusChanged(GetFoldStatus()); NotifyDisplayModeChanged(GetFoldDisplayMode()); } int64_t delayTime = 0; if (g_foldScreenFlag && oldScbDisplayMode_ != GetFoldDisplayMode() && !FoldScreenStateInternel::IsDualDisplayFoldDevice()) { delayTime = SWITCH_USER_DISPLAYMODE_CHANGE_DELAY; auto foldStatus = GetFoldStatus(); TLOGE(WmsLogTag::DMS, "old mode: %{public}u, cur mode: %{public}u", oldScbDisplayMode_, GetFoldDisplayMode()); if (foldStatus == FoldStatus::EXPAND || foldStatus == FoldStatus::HALF_FOLD) { screenSession->UpdatePropertyByFoldControl(GetPhyScreenProperty(SCREEN_ID_FULL)); screenSession->PropertyChange(screenSession->GetScreenProperty(), ScreenPropertyChangeReason::FOLD_SCREEN_EXPAND); } else if (foldStatus == FoldStatus::FOLDED) { screenSession->UpdatePropertyByFoldControl(GetPhyScreenProperty(SCREEN_ID_MAIN)); screenSession->PropertyChange(screenSession->GetScreenProperty(), ScreenPropertyChangeReason::FOLD_SCREEN_FOLDING); } else { TLOGE(WmsLogTag::DMS, "unsupport foldStatus: %{public}u", foldStatus); } } else { screenSession->UpdateValidRotationToScb(); } auto task = [=] { if (!clientProxy_) { TLOGE(WmsLogTag::DMS, "ScbStatusRecoveryWhenSwitchUser clientProxy_ is null"); return; } clientProxy_->SwitchUserCallback(oldScbPids, newScbPid); }; taskScheduler_->PostAsyncTask(task, "clientProxy_ SwitchUserCallback task", delayTime); } void ScreenSessionManager::SetClient(const sptr& client) { if (!SessionPermission::IsSystemCalling()) { TLOGE(WmsLogTag::DMS, "permission denied, calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return; } if (!client) { TLOGE(WmsLogTag::DMS, "SetClient client is null"); return; } clientProxy_ = client; auto userId = GetUserIdByCallingUid(); auto newScbPid = IPCSkeleton::GetCallingPid(); std::ostringstream oss; oss << "set client userId: " << userId << " newScbPid: " << newScbPid << " clientName: " << SysCapUtil::GetClientName(); TLOGI(WmsLogTag::DMS, "%{public}s", oss.str().c_str()); screenEventTracker_.RecordEvent(oss.str()); MockSessionManagerService::GetInstance().NotifyWMSConnected(userId, GetDefaultScreenId(), true); NotifyClientProxyUpdateFoldDisplayMode(GetFoldDisplayMode()); SetClientInner(); SwitchScbNodeHandle(userId, newScbPid, true); AddScbClientDeathRecipient(client, newScbPid); } void ScreenSessionManager::SwitchScbNodeHandle(int32_t newUserId, int32_t newScbPid, bool coldBoot) { std::ostringstream oss; oss << "currentUserId: " << currentUserId_ << " currentScbPId: " << currentScbPId_ << " newUserId: " << newUserId << " newScbPid: " << newScbPid << " coldBoot: " << static_cast(coldBoot); TLOGI(WmsLogTag::DMS, "%{public}s", oss.str().c_str()); screenEventTracker_.RecordEvent(oss.str()); std::unique_lock lock(oldScbPidsMutex_); if (currentScbPId_ != INVALID_SCB_PID) { auto pidIter = std::find(oldScbPids_.begin(), oldScbPids_.end(), currentScbPId_); if (pidIter == oldScbPids_.end() && currentScbPId_ > 0) { oldScbPids_.emplace_back(currentScbPId_); } oldScbPids_.erase(std::remove(oldScbPids_.begin(), oldScbPids_.end(), newScbPid), oldScbPids_.end()); if (oldScbPids_.size() == 0) { TLOGE(WmsLogTag::DMS, "swicth user failed, oldScbPids is null"); screenEventTracker_.RecordEvent("swicth user failed, oldScbPids is null"); } } if (!clientProxy_) { TLOGE(WmsLogTag::DMS, "clientProxy is null"); return; } if (coldBoot) { clientProxy_->SwitchUserCallback(oldScbPids_, newScbPid); clientProxyMap_[newUserId] = clientProxy_; } else { // hot switch if (clientProxyMap_.count(newUserId) == 0) { TLOGE(WmsLogTag::DMS, "not found client proxy. userId:%{public}d.", newUserId); return; } if (newUserId == currentUserId_) { TLOGI(WmsLogTag::DMS, "switch user not change"); return; } clientProxy_ = clientProxyMap_[newUserId]; ScbStatusRecoveryWhenSwitchUser(oldScbPids_, newScbPid); } UpdateDisplayScaleState(GetDefaultScreenId()); currentUserId_ = newUserId; currentScbPId_ = newScbPid; scbSwitchCV_.notify_all(); oldScbDisplayMode_ = GetFoldDisplayMode(); } void ScreenSessionManager::SetClientInner() { std::lock_guard lock(screenSessionMapMutex_); for (const auto& iter : screenSessionMap_) { if (!iter.second) { continue; } // In the rotating state, after scb restarts, the screen information needs to be reset. float phyWidth = 0.0f; float phyHeight = 0.0f; bool isReset = true; GetCurrentScreenPhyBounds(phyWidth, phyHeight, isReset, iter.first); auto localRotation = iter.second->GetRotation(); TLOGI(WmsLogTag::DMS, "phyWidth = :%{public}f, phyHeight = :%{public}f, localRotation = :%{public}u", phyWidth, phyHeight, localRotation); bool isModeChanged = localRotation != Rotation::ROTATION_0; if (isModeChanged && isReset) { TLOGI(WmsLogTag::DMS, "screen(id:%{public}" PRIu64 ") current is not default mode, reset it", iter.first); SetRotation(iter.first, Rotation::ROTATION_0, false); iter.second->SetDisplayBoundary(RectF(0, 0, phyWidth, phyHeight), 0); } if (!clientProxy_) { TLOGE(WmsLogTag::DMS, "clientProxy is null"); return; } clientProxy_->OnScreenConnectionChanged(iter.first, ScreenEvent::CONNECTED, iter.second->GetRSScreenId(), iter.second->GetName()); } } void ScreenSessionManager::GetCurrentScreenPhyBounds(float& phyWidth, float& phyHeight, bool& isReset, const ScreenId& screenid) { if (foldScreenController_ != nullptr) { FoldDisplayMode displayMode = GetFoldDisplayMode(); TLOGI(WmsLogTag::DMS, "fold screen with screenId = %{public}u", displayMode); if (displayMode == FoldDisplayMode::MAIN) { auto phyBounds = GetPhyScreenProperty(SCREEN_ID_MAIN).GetPhyBounds(); phyWidth = phyBounds.rect_.width_; phyHeight = phyBounds.rect_.height_; } else if (displayMode == FoldDisplayMode::FULL) { auto phyBounds = GetPhyScreenProperty(SCREEN_ID_FULL).GetPhyBounds(); phyWidth = phyBounds.rect_.width_; phyHeight = phyBounds.rect_.height_; if (g_screenRotationOffSet == ROTATION_90 || g_screenRotationOffSet == ROTATION_270) { std::swap(phyWidth, phyHeight); } } else { isReset = false; } } else { int id = HiviewDFX::XCollie::GetInstance().SetTimer("GetCurrentScreenPhyBounds", XCOLLIE_TIMEOUT_10S, nullptr, nullptr, HiviewDFX::XCOLLIE_FLAG_LOG); auto remoteScreenMode = rsInterface_.GetScreenActiveMode(screenid); HiviewDFX::XCollie::GetInstance().CancelTimer(id); phyWidth = remoteScreenMode.GetScreenWidth(); phyHeight = remoteScreenMode.GetScreenHeight(); } } ScreenProperty ScreenSessionManager::GetScreenProperty(ScreenId screenId) { DmsXcollie dmsXcollie("DMS:GetScreenProperty", XCOLLIE_TIMEOUT_10S); auto screenSession = GetScreenSession(screenId); if (!screenSession) { TLOGI(WmsLogTag::DMS, "GetScreenProperty screenSession is null"); return {}; } return screenSession->GetScreenProperty(); } std::shared_ptr ScreenSessionManager::GetDisplayNode(ScreenId screenId) { DmsXcollie dmsXcollie("DMS:GetDisplayNode", XCOLLIE_TIMEOUT_10S); auto screenSession = GetScreenSession(screenId); if (!screenSession) { TLOGE(WmsLogTag::DMS, "GetDisplayNode screenSession is null"); return nullptr; } return screenSession->GetDisplayNode(); } int ScreenSessionManager::Dump(int fd, const std::vector& args) { TLOGI(WmsLogTag::DMS, "Dump begin"); sptr dumper = new ScreenSessionDumper(fd, args); if (dumper == nullptr) { TLOGE(WmsLogTag::DMS, "dumper is nullptr"); return -1; } dumper->DumpFreezedPidList(freezedPidList_); dumper->DumpEventTracker(screenEventTracker_); dumper->DumpMultiUserInfo(oldScbPids_, currentUserId_, currentScbPId_); dumper->ExcuteDumpCmd(); TLOGI(WmsLogTag::DMS, "dump end"); return 0; } int ScreenSessionManager::NotifyFoldStatusChanged(const std::string& statusParam) { TLOGI(WmsLogTag::DMS, "NotifyFoldStatusChanged is dump log"); if (statusParam.empty()) { return -1; } FoldStatus foldStatus = FoldStatus::UNKNOWN; FoldDisplayMode displayMode = FoldDisplayMode::UNKNOWN; if (statusParam == STATUS_FOLD_HALF) { foldStatus = FoldStatus::HALF_FOLD; displayMode = FoldDisplayMode::FULL; } else if (statusParam == STATUS_EXPAND) { foldStatus = FoldStatus::EXPAND; displayMode = FoldDisplayMode::FULL; } else if (statusParam == STATUS_FOLD) { foldStatus = FoldStatus::FOLDED; displayMode = FoldDisplayMode::MAIN; } else { TLOGW(WmsLogTag::DMS, "NotifyFoldStatusChanged status not support"); return -1; } SetFoldDisplayMode(displayMode); if (foldScreenController_ != nullptr) { foldScreenController_->SetFoldStatus(foldStatus); } NotifyFoldStatusChanged(foldStatus); return 0; } void ScreenSessionManager::NotifyAvailableAreaChanged(DMRect area) { TLOGI(WmsLogTag::DMS, "NotifyAvailableAreaChanged call"); auto agents = dmAgentContainer_.GetAgentsByType(DisplayManagerAgentType::AVAILABLE_AREA_CHANGED_LISTENER); if (agents.empty()) { TLOGI(WmsLogTag::DMS, "NotifyAvailableAreaChanged agents is empty"); return; } for (auto& agent : agents) { int32_t agentPid = dmAgentContainer_.GetAgentPid(agent); if (!IsFreezed(agentPid, DisplayManagerAgentType::AVAILABLE_AREA_CHANGED_LISTENER)) { agent->NotifyAvailableAreaChanged(area); } } } DMError ScreenSessionManager::GetAvailableArea(DisplayId displayId, DMRect& area) { auto displayInfo = GetDisplayInfoById(displayId); if (displayInfo == nullptr) { TLOGE(WmsLogTag::DMS, "can not get displayInfo."); return DMError::DM_ERROR_NULLPTR; } auto screenSession = GetScreenSession(displayInfo->GetScreenId()); if (screenSession == nullptr) { TLOGE(WmsLogTag::DMS, "can not get default screen now"); return DMError::DM_ERROR_NULLPTR; } area = screenSession->GetAvailableArea(); return DMError::DM_OK; } void ScreenSessionManager::UpdateAvailableArea(ScreenId screenId, DMRect area) { if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "update available area permission denied!"); return; } auto screenSession = GetScreenSession(screenId); if (screenSession == nullptr) { TLOGE(WmsLogTag::DMS, "can not get default screen now"); return; } if (!screenSession->UpdateAvailableArea(area)) { return; } NotifyAvailableAreaChanged(area); } void ScreenSessionManager::NotifyFoldToExpandCompletion(bool foldToExpand) { TLOGI(WmsLogTag::DMS, "NotifyFoldToExpandCompletion ENTER"); if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "permission denied, clientName: %{public}s, pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return; } if (!FoldScreenStateInternel::IsDualDisplayFoldDevice()) { SetDisplayNodeScreenId(SCREEN_ID_FULL, foldToExpand ? SCREEN_ID_FULL : SCREEN_ID_MAIN); } /* Avoid fold to expand process queues */ if (foldScreenController_ != nullptr) { foldScreenController_->SetdisplayModeChangeStatus(false); } sptr screenSession = GetDefaultScreenSession(); if (screenSession == nullptr) { TLOGE(WmsLogTag::DMS, "fail to get default screenSession"); return; } screenSession->UpdateRotationAfterBoot(foldToExpand); } void ScreenSessionManager::CheckAndSendHiSysEvent(const std::string& eventName, const std::string& bundleName) const { HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "ssm:CheckAndSendHiSysEvent"); if (eventName != "CREATE_VIRTUAL_SCREEN") { if (!Permission::CheckIsCallingBundleName(bundleName)) { TLOGD(WmsLogTag::DMS, "BundleName not in whitelist!"); return; } } int32_t eventRet = HiSysEventWrite( OHOS::HiviewDFX::HiSysEvent::Domain::WINDOW_MANAGER, eventName, // CREATE_VIRTUAL_SCREEN, GET_DISPLAY_SNAPSHOT OHOS::HiviewDFX::HiSysEvent::EventType::STATISTIC, "PID", getpid(), "UID", getuid()); TLOGI(WmsLogTag::DMS, "%{public}s: Write HiSysEvent ret:%{public}d", eventName.c_str(), eventRet); } DMError ScreenSessionManager::ProxyForFreeze(const std::set& pidList, bool isProxy) { if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "permission denied!"); return DMError::DM_ERROR_NOT_SYSTEM_APP; } { std::lock_guard lock(freezedPidListMutex_); for (auto pid : pidList) { if (isProxy) { freezedPidList_.insert(pid); } else { freezedPidList_.erase(pid); // set删除不存在的元素不会引发异常 } } } if (isProxy) { return DMError::DM_OK; } // 进程解冻时刷新一次displaychange sptr screenSession = GetScreenSession(GetDefaultScreenId()); if (!screenSession) { return DMError::DM_ERROR_NULLPTR; } auto task = [=] { NotifyUnfreezed(pidList, screenSession); }; taskScheduler_->PostAsyncTask(task, "ProxyForUnFreeze NotifyDisplayChanged"); return DMError::DM_OK; } void ScreenSessionManager::NotifyUnfreezedAgents(const int32_t& pid, const std::set& unfreezedPidList, const std::set& pidAgentTypes, const sptr& screenSession) { bool isAgentTypeNotify = false; for (auto agentType : pidAgentTypes) { auto agents = dmAgentContainer_.GetAgentsByType(agentType); for (auto agent : agents) { int32_t agentPid = dmAgentContainer_.GetAgentPid(agent); if (agentPid != pid || unfreezedPidList.count(pid) == 0) { continue; } isAgentTypeNotify = true; if (agentType == DisplayManagerAgentType::DISPLAY_EVENT_LISTENER) { agent->OnDisplayChange(screenSession->ConvertToDisplayInfo(), DisplayChangeEvent::DISPLAY_UNFREEZED); } else if (agentType == DisplayManagerAgentType::DISPLAY_MODE_CHANGED_LISTENER) { FoldDisplayMode displayMode = GetFoldDisplayMode(); agent->NotifyDisplayModeChanged(displayMode); } else if (agentType == DisplayManagerAgentType::FOLD_STATUS_CHANGED_LISTENER) { FoldStatus foldStatus = GetFoldStatus(); agent->NotifyFoldStatusChanged(foldStatus); } else if (agentType == DisplayManagerAgentType::FOLD_ANGLE_CHANGED_LISTENER) { std::lock_guard lock(lastStatusUpdateMutex_); agent->NotifyFoldAngleChanged(lastFoldAngles_); } else if (agentType == DisplayManagerAgentType::SCREEN_EVENT_LISTENER) { auto displayInfo = screenSession->ConvertToDisplayInfo(); auto screenInfo = GetScreenInfoById(displayInfo->GetScreenId()); std::lock_guard lock(lastStatusUpdateMutex_); agent->OnScreenChange(screenInfo, lastScreenChangeEvent_); } else if (agentType == DisplayManagerAgentType::DISPLAY_UPDATE_LISTENER) { std::lock_guard lock(lastStatusUpdateMutex_); agent->NotifyDisplayChangeInfoChanged(lastDisplayChangeInfo_); } else { isAgentTypeNotify = false; TLOGI(WmsLogTag::DMS, "Unknown agentType."); } } if (isAgentTypeNotify) { pidAgentTypeMap_[pid].erase(agentType); } } } void ScreenSessionManager::NotifyUnfreezed(const std::set& unfreezedPidList, const sptr& screenSession) { std::lock_guard lock(freezedPidListMutex_); for (auto iter = pidAgentTypeMap_.begin(); iter != pidAgentTypeMap_.end();) { int32_t pid = iter->first; auto pidAgentTypes = iter->second; NotifyUnfreezedAgents(pid, unfreezedPidList, pidAgentTypes, screenSession); if (pidAgentTypeMap_[pid].empty()) { iter = pidAgentTypeMap_.erase(iter); } else { iter++; } } } DMError ScreenSessionManager::ResetAllFreezeStatus() { if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "permission denied!"); return DMError::DM_ERROR_NOT_SYSTEM_APP; } std::lock_guard lock(freezedPidListMutex_); freezedPidList_.clear(); pidAgentTypeMap_.clear(); TLOGI(WmsLogTag::DMS, "freezedPidList_ has been clear."); return DMError::DM_OK; } void ScreenSessionManager::RegisterApplicationStateObserver() { #ifdef SENSOR_ENABLE std::string identify = IPCSkeleton::ResetCallingIdentity(); FoldScreenSensorManager::GetInstance().RegisterApplicationStateObserver(); IPCSkeleton::SetCallingIdentity(identify); #endif } DeviceScreenConfig ScreenSessionManager::GetDeviceScreenConfig() { return deviceScreenConfig_; } void ScreenSessionManager::SetVirtualScreenBlackList(ScreenId screenId, std::vector& windowIdList) { if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "permission denied!"); return; } TLOGI(WmsLogTag::DMS, "Enter, screenId: %{public}" PRIu64, screenId); if (windowIdList.empty()) { TLOGE(WmsLogTag::DMS, "WindowIdList is empty"); return; } ScreenId rsScreenId = SCREEN_ID_INVALID; if (!ConvertScreenIdToRsScreenId(screenId, rsScreenId)) { TLOGE(WmsLogTag::DMS, "No corresponding rsId"); return; } if (!clientProxy_) { TLOGE(WmsLogTag::DMS, "clientProxy_ is nullptr"); return; } std::vector surfaceNodeIds; clientProxy_->OnGetSurfaceNodeIdsFromMissionIdsChanged(windowIdList, surfaceNodeIds, true); rsInterface_.SetVirtualScreenBlackList(rsScreenId, surfaceNodeIds); } void ScreenSessionManager::DisablePowerOffRenderControl(ScreenId screenId) { if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "permission denied!"); return; } TLOGI(WmsLogTag::DMS, "Enter, screenId: %{public}" PRIu64, screenId); ScreenId rsScreenId = SCREEN_ID_INVALID; if (!ConvertScreenIdToRsScreenId(screenId, rsScreenId)) { TLOGE(WmsLogTag::DMS, "No corresponding rsId"); return; } rsInterface_.DisablePowerOffRenderControl(rsScreenId); } void ScreenSessionManager::ReportFoldStatusToScb(std::vector& screenFoldInfo) { if (clientProxy_) { auto screenInfo = GetDefaultScreenSession(); int32_t rotation = -1; if (screenInfo != nullptr) { rotation = static_cast(screenInfo->GetRotation()); } screenFoldInfo.emplace_back(std::to_string(rotation)); clientProxy_->OnFoldStatusChangedReportUE(screenFoldInfo); } } std::vector ScreenSessionManager::GetAllDisplayPhysicalResolution() { if (allDisplayPhysicalResolution_.empty()) { sptr defaultScreen = GetDefaultScreenSession(); if (defaultScreen == nullptr) { TLOGE(WmsLogTag::DMS, "default screen null"); return allDisplayPhysicalResolution_; } ScreenProperty defaultScreenProperty = defaultScreen->GetScreenProperty(); DisplayPhysicalResolution defaultSize; defaultSize.foldDisplayMode_ = FoldDisplayMode::UNKNOWN; defaultSize.physicalWidth_ = defaultScreenProperty.GetPhyBounds().rect_.width_; defaultSize.physicalHeight_ = defaultScreenProperty.GetPhyBounds().rect_.height_; allDisplayPhysicalResolution_.emplace_back(defaultSize); } return allDisplayPhysicalResolution_; } DMError ScreenSessionManager::SetVirtualScreenSecurityExemption(ScreenId screenId, uint32_t pid, std::vector& windowIdList) { if (!(Permission::IsSystemCalling() && Permission::CheckCallingPermission(SCREEN_CAPTURE_PERMISSION)) && !SessionPermission::IsShellCall()) { TLOGE(WmsLogTag::DMS, "permission denied!"); return DMError::DM_ERROR_INVALID_CALLING; } std::vector surfaceNodeIds; if (!windowIdList.empty()) { MockSessionManagerService::GetInstance().GetProcessSurfaceNodeIdByPersistentId( pid, windowIdList, surfaceNodeIds); } auto rsId = screenIdManager_.ConvertToRsScreenId(screenId); auto ret = rsInterface_.SetVirtualScreenSecurityExemptionList(rsId, surfaceNodeIds); std::ostringstream oss; oss << "screenId:" << screenId << ", rsID: " << rsId << ", pid: " << pid << ", winListSize:[ "; for (auto val : windowIdList) { oss << val << " "; } oss << "]" << ", surfaceListSize:[ "; for (auto val : surfaceNodeIds) { oss << val << " "; } oss << "]" << ", ret: " << ret; TLOGI(WmsLogTag::DMS, "%{public}s", oss.str().c_str()); return ret == 0 ? DMError::DM_OK : DMError::DM_ERROR_UNKNOWN; } void ScreenSessionManager::OnTentModeChanged(bool isTentMode) { if (!foldScreenController_) { TLOGI(WmsLogTag::DMS, "foldScreenController_ is null"); return; } foldScreenController_->OnTentModeChanged(isTentMode); } void ScreenSessionManager::SetCoordinationFlag(bool isCoordinationFlag) { TLOGI(WmsLogTag::DMS, "set coordination flag %{public}d", isCoordinationFlag); isCoordinationFlag_ = isCoordinationFlag; } DMError ScreenSessionManager::SetVirtualScreenMaxRefreshRate(ScreenId id, uint32_t refreshRate, uint32_t& actualRefreshRate) { if (!SessionPermission::IsSystemCalling()) { TLOGE(WmsLogTag::DMS, "permission denied! calling clientName: %{public}s, calling pid: %{public}d", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingPid()); return DMError::DM_ERROR_NOT_SYSTEM_APP; } TLOGI(WmsLogTag::DMS, "ID:%{public}" PRIu64", refreshRate:%{public}u, actualRefreshRate:%{public}u", id, refreshRate, actualRefreshRate); if (id == GetDefaultScreenId()) { TLOGE(WmsLogTag::DMS, "cannot set refresh rate of main screen, main screen id: %{public}" PRIu64".", GetDefaultScreenId()); return DMError::DM_ERROR_INVALID_PARAM; } auto screenSession = GetScreenSession(id); if (screenSession == nullptr) { TLOGE(WmsLogTag::DMS, "screenSession is null."); return DMError::DM_ERROR_INVALID_PARAM; } ScreenId rsScreenId; if (!screenIdManager_.ConvertToRsScreenId(id, rsScreenId)) { TLOGE(WmsLogTag::DMS, "No corresponding rsId."); return DMError::DM_ERROR_INVALID_PARAM; } int32_t res = rsInterface_.SetVirtualScreenRefreshRate(rsScreenId, refreshRate, actualRefreshRate); TLOGI(WmsLogTag::DMS, "refreshRate:%{public}u, actualRefreshRate:%{public}u", refreshRate, actualRefreshRate); if (res != StatusCode::SUCCESS) { TLOGE(WmsLogTag::DMS, "rsInterface error: %{public}d", res); return DMError::DM_ERROR_INVALID_PARAM; } screenSession->UpdateRefreshRate(actualRefreshRate); return DMError::DM_OK; } void ScreenSessionManager::OnScreenCaptureNotify(ScreenId mainScreenId, int32_t uid, const std::string& clientName) { if (!clientProxy_) { TLOGI(WmsLogTag::DMS, "clientProxy_ is null"); return; } clientProxy_->ScreenCaptureNotify(mainScreenId, uid, clientName); } void ScreenSessionManager::AddPermissionUsedRecord(const std::string& permission, int32_t successCount, int32_t failCount) { int32_t ret = Security::AccessToken::PrivacyKit::AddPermissionUsedRecord(IPCSkeleton::GetCallingTokenID(), permission, successCount, failCount); if (ret != 0) { TLOGW(WmsLogTag::DMS, "permission:%{public}s, successCount %{public}d, failedCount %{public}d", permission.c_str(), successCount, failCount); } } std::shared_ptr ScreenSessionManager::GetScreenCapture(const CaptureOption& captureOption, DmErrorCode* errorCode) { TLOGI(WmsLogTag::DMS, "enter!"); if (errorCode == nullptr) { TLOGE(WmsLogTag::DMS, "param is null."); return nullptr; } if (system::GetBoolParameter("persist.edm.disallow_screenshot", false)) { TLOGW(WmsLogTag::DMS, "capture disabled by edm!"); *errorCode = DmErrorCode::DM_ERROR_NO_PERMISSION; return nullptr; } if (!ScreenSceneConfig::IsSupportCapture()) { TLOGW(WmsLogTag::DMS, "device not support capture."); *errorCode = DmErrorCode::DM_ERROR_DEVICE_NOT_SUPPORT; return nullptr; } if (!Permission::CheckCallingPermission(CUSTOM_SCREEN_CAPTURE_PERMISSION) && !SessionPermission::IsShellCall()) { TLOGE(WmsLogTag::DMS, "Permission Denied! clientName: %{public}s, pid: %{public}d.", SysCapUtil::GetClientName().c_str(), IPCSkeleton::GetCallingRealPid()); *errorCode = DmErrorCode::DM_ERROR_NO_PERMISSION; return nullptr; } if (captureOption.displayId_ == DISPLAY_ID_INVALID) { TLOGE(WmsLogTag::DMS, "display id invalid."); *errorCode = DmErrorCode::DM_ERROR_INVALID_PARAM; return nullptr; } HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "ssm:GetScreenCapture(%" PRIu64")", captureOption.displayId_); auto res = GetScreenSnapshot(captureOption.displayId_, false); AddPermissionUsedRecord(CUSTOM_SCREEN_CAPTURE_PERMISSION, static_cast(res != nullptr), static_cast(res == nullptr)); if (res == nullptr) { TLOGE(WmsLogTag::DMS, "get capture null."); *errorCode = DmErrorCode::DM_ERROR_SYSTEM_INNORMAL; return nullptr; } NotifyScreenshot(captureOption.displayId_); if (SessionPermission::IsBetaVersion()) { CheckAndSendHiSysEvent("GET_DISPLAY_SNAPSHOT", "hmos.screenshot"); } *errorCode = DmErrorCode::DM_OK; isScreenShot_ = true; /* notify scb to do toast */ OnScreenCaptureNotify(GetDefaultScreenId(), IPCSkeleton::GetCallingUid(), SysCapUtil::GetClientName()); /* notify application capture happend */ NotifyCaptureStatusChanged(); return res; } sptr ScreenSessionManager::GetPrimaryDisplayInfo() { DmsXcollie dmsXcollie("DMS:GetPrimaryDisplayInfo", XCOLLIE_TIMEOUT_10S); sptr screenSession = nullptr; { std::lock_guard lock(screenSessionMapMutex_); for (auto sessionIt : screenSessionMap_) { screenSession = sessionIt.second; if (screenSession == nullptr) { TLOGE(WmsLogTag::DMS, "screenSession is nullptr!"); continue; } if (!screenSession->GetIsExtend()) { TLOGE(WmsLogTag::DMS, "find primary %{public}" PRIu64, screenSession->screenId_); break; } } } if (screenSession == nullptr) { TLOGW(WmsLogTag::DMS, "get extend screen faild use default!"); screenSession = GetScreenSession(GetDefaultScreenId()); } if (screenSession) { std::lock_guard lock_info(displayInfoMutex_); sptr displayInfo = screenSession->ConvertToDisplayInfo(); if (displayInfo == nullptr) { TLOGI(WmsLogTag::DMS, "convert display error."); return nullptr; } displayInfo = HookDisplayInfoByUid(displayInfo, screenSession); return displayInfo; } else { TLOGE(WmsLogTag::DMS, "failed"); return nullptr; } } int32_t ScreenSessionManager::GetCameraStatus() { return cameraStatus_; } int32_t ScreenSessionManager::GetCameraPosition() { return cameraPosition_; } } // namespace OHOS::Rosen