diff --git a/window_scene/screen_session_manager/BUILD.gn b/window_scene/screen_session_manager/BUILD.gn index a87e74419cbd1673309298ea89e13e99fffb534b..2e2cd2152e6da4b44e378ea0a68266a90845857e 100644 --- a/window_scene/screen_session_manager/BUILD.gn +++ b/window_scene/screen_session_manager/BUILD.gn @@ -67,6 +67,7 @@ ohos_shared_library("screen_session_manager") { "src/publish/screen_session_publish.cpp", "src/screen_cutout_controller.cpp", "src/screen_edid_parse.cpp", + "src/screen_power_utils.cpp", "src/screen_rotation_property.cpp", "src/screen_scene_config.cpp", "src/screen_sensor_connector.cpp", diff --git a/window_scene/screen_session_manager/include/screen_power_utils.h b/window_scene/screen_session_manager/include/screen_power_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..75ddd0bd053dc58c2d5730999b87ad762b342390 --- /dev/null +++ b/window_scene/screen_session_manager/include/screen_power_utils.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2025 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. + */ + +#ifndef SCREEN_POWER_UTILS_H +#define SCREEN_POWER_UTILS_H + +#include +#include + +namespace OHOS { +namespace Rosen { +class ScreenPowerUtils { +public: + ScreenPowerUtils() {} + ~ScreenPowerUtils() {} + static void EnablePowerForceTimingOut(); + static void DisablePowerForceTimingOut(); + static void LightAndLockScreen(const std::string& detail); + static bool GetEnablePowerForceTimingOut(); + +private: + static std::mutex powerTimingMutex_; + static bool isEnablePowerForceTimingOut_; +}; +} // Rosen +} // OHOS +#endif + diff --git a/window_scene/screen_session_manager/include/screen_session_manager.h b/window_scene/screen_session_manager/include/screen_session_manager.h index d5bf9bc0512788f94a843282ad1fac6e391146fc..63cdbcac2a325c7c4289865c310b68a81fd29116 100644 --- a/window_scene/screen_session_manager/include/screen_session_manager.h +++ b/window_scene/screen_session_manager/include/screen_session_manager.h @@ -209,6 +209,8 @@ public: const std::vector>& screenInfos, ScreenGroupChangeEvent groupEvent); void OnScreenshot(sptr info); bool IsMultiScreenCollaboration(); + bool HasCastEngineOrPhyMirror(const std::vector& screenIdsToExclude); + void HandlePhysicalMirrorConnect(sptr screenSession, bool phyMirrorEnable); sptr GetCutoutInfo(DisplayId displayId) override; DMError HasImmersiveWindow(ScreenId screenId, bool& immersive) override; void SetDisplayBoundary(const sptr screenSession); @@ -616,6 +618,7 @@ private: std::atomic isPhyScreenConnected_ = false; int32_t cameraStatus_ = {0}; int32_t cameraPosition_ = {0}; + PowerStateChangeReason powerStateChangeReason_ = PowerStateChangeReason::STATE_CHANGE_REASON_UNKNOWN; // Fold Screen std::map phyScreenPropMap_; diff --git a/window_scene/screen_session_manager/src/multi_screen_manager.cpp b/window_scene/screen_session_manager/src/multi_screen_manager.cpp index 0a5d4ded62ff230e2b174737c003f1470fa03015..50f15c1b76c12428ab25f50068b25d62215ff607 100644 --- a/window_scene/screen_session_manager/src/multi_screen_manager.cpp +++ b/window_scene/screen_session_manager/src/multi_screen_manager.cpp @@ -14,6 +14,8 @@ */ #include "multi_screen_manager.h" +#include "screen_power_utils.h" +#include "screen_scene_config.h" #ifdef RES_SCHED_ENABLE #include "res_sched_client.h" #include "res_type.h" @@ -240,6 +242,10 @@ DMError MultiScreenManager::UniqueSwitch(const std::vector& screenIds, ScreenSessionManager::GetInstance().UnregisterSettingWireCastObserver(screenId); } } + if (!ScreenSessionManager::GetInstance().HasCastEngineOrPhyMirror(physicalScreenIds) && + switchStatus == DMError::DM_OK && ScreenSceneConfig::GetExternalScreenDefaultMode() != "none") { + ScreenPowerUtils::DisablePowerForceTimingOut(); + } TLOGW(WmsLogTag::DMS, "physical screen switch to unique result: %{public}d", switchStatus); AddUniqueScreenDisplayId(displayIds, physicalScreenIds, switchStatus); } @@ -275,6 +281,11 @@ DMError MultiScreenManager::MirrorSwitch(const ScreenId mainScreenId, const std: auto screenSession = ScreenSessionManager::GetInstance().GetScreenSession(screenId); ScreenSessionManager::GetInstance().RegisterSettingWireCastObserver(screenSession); } + // switchStatus is DM_OK and device is not PC + if (ScreenSceneConfig::GetExternalScreenDefaultMode() != "none") { + ScreenPowerUtils::EnablePowerForceTimingOut(); + ScreenSessionManager::GetInstance().DisablePowerOffRenderControl(0); + } } TLOGW(WmsLogTag::DMS, "physical screen switch to mirror result: %{public}d", switchStatus); } diff --git a/window_scene/screen_session_manager/src/screen_power_utils.cpp b/window_scene/screen_session_manager/src/screen_power_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e12cc495dce4bf6f3a2e842790d0aca8624e6589 --- /dev/null +++ b/window_scene/screen_session_manager/src/screen_power_utils.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2025 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 "screen_power_utils.h" +#include "power_mgr_client.h" +#include "window_manager_hilog.h" + +using namespace OHOS::PowerMgr; + +namespace OHOS { +namespace Rosen { + +std::mutex ScreenPowerUtils::powerTimingMutex_; +bool ScreenPowerUtils::isEnablePowerForceTimingOut_ = false; + +void ScreenPowerUtils::EnablePowerForceTimingOut() +{ + std::lock_guard lock(powerTimingMutex_); + TLOGI(WmsLogTag::DMS, "Enable power timeout begin."); + if (isEnablePowerForceTimingOut_) { + TLOGI(WmsLogTag::DMS, "Already enable."); + return; + } + + auto& powerMgrClient = PowerMgrClient::GetInstance(); + PowerErrors setRet = powerMgrClient.SetForceTimingOut(true); + if (setRet != PowerErrors::ERR_OK) { + TLOGE(WmsLogTag::DMS, "SetForceTimingOut failed: %{public}d", setRet); + return; + } + + PowerErrors lockRet = powerMgrClient.LockScreenAfterTimingOut(true, true, false); + if (lockRet != PowerErrors::ERR_OK) { + setRet = powerMgrClient.SetForceTimingOut(false); + TLOGE(WmsLogTag::DMS, "LockScreenAfterTimingOut failed, lockRet: %{public}d, setRet: %{public}d", + lockRet, setRet); + return; + } + isEnablePowerForceTimingOut_ = true; +} + +void ScreenPowerUtils::DisablePowerForceTimingOut() +{ + std::lock_guard lock(powerTimingMutex_); + TLOGI(WmsLogTag::DMS, "Disable power timeout begin."); + if (!isEnablePowerForceTimingOut_) { + TLOGI(WmsLogTag::DMS, "Already disable."); + return; + } + auto& powerMgrClient = PowerMgrClient::GetInstance(); + PowerErrors setRet = powerMgrClient.SetForceTimingOut(false); + if (setRet != PowerErrors::ERR_OK) { + TLOGE(WmsLogTag::DMS, "SetForceTimingOut failed: %{public}d", setRet); + } + + PowerErrors lockRet = powerMgrClient.LockScreenAfterTimingOut(true, false, true); + if (lockRet != PowerErrors::ERR_OK) { + TLOGE(WmsLogTag::DMS, "LockScreenAfterTimingOut failed, lockRet: %{public}d", lockRet); + } + isEnablePowerForceTimingOut_ = false; +} + +void ScreenPowerUtils::LightAndLockScreen(const std::string& detail) +{ + auto& powerMgrClient = PowerMgrClient::GetInstance(); + if (!powerMgrClient.IsScreenOn()) { + PowerErrors wakeupRet = powerMgrClient.WakeupDevice(WakeupDeviceType::WAKEUP_DEVICE_APPLICATION, detail); + PowerErrors suspendRet = powerMgrClient.SuspendDevice(); + TLOGI(WmsLogTag::DMS, "wakeupRet: %{public}d, suspendRet: %{public}d", wakeupRet, suspendRet); + } +} +bool ScreenPowerUtils::GetEnablePowerForceTimingOut() +{ + return isEnablePowerForceTimingOut_; +} +} // Rosen +} // OHOS \ No newline at end of file diff --git a/window_scene/screen_session_manager/src/screen_session_manager.cpp b/window_scene/screen_session_manager/src/screen_session_manager.cpp index 3446465bfc473d41c50fb4d42060738749fcb32e..178e4cc51903f3658fc3dd00834966be19a2afbe 100644 --- a/window_scene/screen_session_manager/src/screen_session_manager.cpp +++ b/window_scene/screen_session_manager/src/screen_session_manager.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include "dm_common.h" #include "fold_screen_state_internel.h" @@ -1081,11 +1082,7 @@ void ScreenSessionManager::HandleScreenConnectEvent(sptr screenSe ScreenId screenId, ScreenEvent screenEvent) { bool phyMirrorEnable = IsDefaultMirrorMode(screenId); - if (phyMirrorEnable) { - PhyMirrorConnectWakeupScreen(); - NotifyCastWhenScreenConnectChange(true); - RegisterSettingWireCastObserver(screenSession); - } + HandlePhysicalMirrorConnect(screenSession, phyMirrorEnable); #ifdef FOLD_ABILITY_ENABLE if (foldScreenController_ != nullptr) { if ((screenId == 0 || (screenId == SCREEN_ID_MAIN && isCoordinationFlag_ == true)) && @@ -1138,6 +1135,13 @@ void ScreenSessionManager::HandleScreenDisconnectEvent(sptr scree NotifyDisplayDestroy(screenSession->GetScreenId()); NotifyCastWhenScreenConnectChange(false); FreeDisplayMirrorNodeInner(screenSession); + if (!g_isPcDevice) { + std::vector screenIdsToExclude = { screenId }; + if (!HasCastEngineOrPhyMirror(screenIdsToExclude)) { + ScreenPowerUtils::DisablePowerForceTimingOut(); + ScreenPowerUtils::LightAndLockScreen("light and lock screen"); + } + } } HandlePCScreenDisconnect(screenSession); #ifdef WM_MULTI_SCREEN_ENABLE @@ -1171,6 +1175,19 @@ void ScreenSessionManager::HandleScreenDisconnectEvent(sptr scree TLOGW(WmsLogTag::DMS, "disconnect success. ScreenId: %{public}" PRIu64 "", screenId); } +void ScreenSessionManager::HandlePhysicalMirrorConnect(sptr screenSession, bool phyMirrorEnable) +{ + if (phyMirrorEnable) { + PhyMirrorConnectWakeupScreen(); + NotifyCastWhenScreenConnectChange(true); + RegisterSettingWireCastObserver(screenSession); + if (!g_isPcDevice) { + ScreenPowerUtils::EnablePowerForceTimingOut(); + DisablePowerOffRenderControl(0); + } + } +} + void ScreenSessionManager::HandlePCScreenDisconnect(sptr screenSession) { ScreenCombination screenCombination = screenSession->GetScreenCombination(); @@ -2412,7 +2429,8 @@ bool ScreenSessionManager::WakeUpEnd() bool ScreenSessionManager::SuspendBegin(PowerStateChangeReason reason) { - // 该接口当前只有Power调用 + // only power use + powerStateChangeReason_ = reason; HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "[UL_POWER]ssm:SuspendBegin(%u)", reason); if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { TLOGE(WmsLogTag::DMS, "permission denied! calling: %{public}s, pid: %{public}d", @@ -3054,6 +3072,24 @@ void ScreenSessionManager::TriggerDisplayModeUpdate(FoldDisplayMode targetDispla void ScreenSessionManager::CallRsSetScreenPowerStatusSync(ScreenId screenId, ScreenPowerStatus status) { auto rsSetScreenPowerStatusTask = [=] { + bool phyMirrorEnable = IsDefaultMirrorMode(screenId); + if (phyMirrorEnable && !g_isPcDevice) { + auto screenSession = GetScreenSession(screenId); + if (screenSession == nullptr) { + return; + } + auto sourceMode = screenSession->GetSourceMode(); + if (sourceMode == ScreenSourceMode::SCREEN_MIRROR && + status != ScreenPowerStatus::POWER_STATUS_ON && + powerStateChangeReason_ == PowerStateChangeReason::STATE_CHANGE_REASON_COLLABORATION) { + return; + } + if (sourceMode == ScreenSourceMode::SCREEN_UNIQUE && + status != ScreenPowerStatus::POWER_STATUS_ON && + powerStateChangeReason_ == PowerStateChangeReason::STATE_CHANGE_REASON_HARD_KEY) { + return; + } + } rsInterface_.SetScreenPowerStatus(screenId, status); }; screenPowerTaskScheduler_->PostVoidSyncTask(rsSetScreenPowerStatusTask, "rsInterface_.SetScreenPowerStatus task"); @@ -6379,6 +6415,33 @@ bool ScreenSessionManager::IsMultiScreenCollaboration() return isMultiScreenCollaboration_; } +bool ScreenSessionManager::HasCastEngineOrPhyMirror(const std::vector& screenIdsToExclude) +{ + std::lock_guard lock(screenSessionMapMutex_); + for (auto sessionItem : screenSessionMap_) { + auto screenId = sessionItem.first; + auto screenSession = sessionItem.second; + if (screenSession == nullptr) { + TLOGI(WmsLogTag::DMS, "screenSession is null"); + continue; + } + if (std::find(screenIdsToExclude.begin(), screenIdsToExclude.end(), screenId) != screenIdsToExclude.end()) { + continue; + } + auto screenType = screenSession->GetScreenProperty().GetScreenType(); + if (screenType == ScreenType::VIRTUAL + && screenSession->GetName() == "CastEngine") { + return true; + } + + if (IsDefaultMirrorMode(screenId) && screenType == ScreenType::REAL && + screenSession->GetScreenCombination() == ScreenCombination::SCREEN_MIRROR) { + return true; + } + } + return false; +} + FoldStatus ScreenSessionManager::GetFoldStatus() { #ifdef FOLD_ABILITY_ENABLE diff --git a/window_scene/test/dms_unittest/BUILD.gn b/window_scene/test/dms_unittest/BUILD.gn index 742431911d703ebba124fdcc566bf810b85aaf47..2f4b2e57dcff3d1b60e72825160234ab2844e82d 100644 --- a/window_scene/test/dms_unittest/BUILD.gn +++ b/window_scene/test/dms_unittest/BUILD.gn @@ -20,6 +20,7 @@ group("unittest") { deps = [ ":ws_screen_cutout_controller_test", + ":ws_screen_power_utils_test", ":ws_screen_property_test", ":ws_screen_rotation_property_test", ":ws_screen_scene_config_test", @@ -561,6 +562,20 @@ ohos_unittest("ws_screen_session_dumper_test") { ] } +ohos_unittest("ws_screen_power_utils_test") { + module_out_path = module_out_path + + sources = [ "screen_power_utils_test.cpp" ] + + deps = [ ":ws_unittest_common" ] + + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + "init:libbegetutil", + ] +} + ohos_unittest("ws_session_display_power_controller_test") { module_out_path = module_out_path diff --git a/window_scene/test/dms_unittest/screen_power_utils_test.cpp b/window_scene/test/dms_unittest/screen_power_utils_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..26091067a84e17a38f351f01c281d5c498f93662 --- /dev/null +++ b/window_scene/test/dms_unittest/screen_power_utils_test.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2025 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 "window_manager_hilog.h" +#include "gtest/gtest.h" +#include "screen_power_utils.h" + +using namespace testing; +using namespace testing::ext; + + +namespace OHOS { +namespace Rosen { +class ScreenPowerUtilsTest : public testing::Test { +public: + static void SetUpTestCase() {} + static void TearDownTestCase() {} + + void SetUp() override; + void TearDown() override; +}; + +void ScreenPowerUtilsTest::SetUp(void) +{} +void ScreenPowerUtilsTest::TearDown(void) +{} + +/** + * @tc.name: ForceTimingOut_001 + * @tc.desc: Test the EnablePowerForceTimingOut/DisablePowerForceTimingOut function + * @tc.type: FUNC + */ +HWTEST_F(ScreenPowerUtilsTest, ForceTimingOut_001, TestSize.Level1) +{ + TLOGI(WmsLogTag::DMS, "EnableForceTimingOut_001"); + EXPECT_FALSE(ScreenPowerUtils::GetEnablePowerForceTimingOut()); + + ScreenPowerUtils::EnablePowerForceTimingOut(); + EXPECT_TRUE(ScreenPowerUtils::GetEnablePowerForceTimingOut()); + + ScreenPowerUtils::DisablePowerForceTimingOut(); + EXPECT_FALSE(ScreenPowerUtils::GetEnablePowerForceTimingOut()); +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file