From 98f5dd15f4a2ddad40c350d84b8bcd9ee3dcf6d7 Mon Sep 17 00:00:00 2001 From: shiyueeee Date: Sun, 30 Jan 2022 17:55:41 +0800 Subject: [PATCH] Set display size as screen mode changes Change-Id: I8c49155056aaa161c483941f4a857fcb2614db34 Signed-off-by: shiyueeee --- dm/include/display_manager_agent.h | 1 + dm/include/display_manager_agent_default.h | 2 +- dm/src/display.cpp | 7 + dm/src/display_manager.cpp | 14 +- dm/src/display_manager_adapter.cpp | 32 +- dm/src/display_manager_agent.cpp | 5 + dm/test/systemtest/BUILD.gn | 12 + dm/test/systemtest/display_change_test.cpp | 276 ++++++++++++++++++ .../include/abstract_display_controller.h | 3 + dmserver/include/abstract_screen_controller.h | 1 + dmserver/src/abstract_display.cpp | 1 + dmserver/src/abstract_display_controller.cpp | 53 +++- dmserver/src/abstract_screen_controller.cpp | 43 +++ .../src/display_manager_agent_controller.cpp | 5 +- dmserver/src/display_manager_service.cpp | 14 +- interfaces/innerkits/dm/display.h | 5 +- interfaces/innerkits/dm/display_manager.h | 4 +- interfaces/innerkits/dm/dm_common.h | 7 + interfaces/innerkits/dm/screen.h | 3 - utils/include/display_change_listener.h | 1 + utils/include/display_info.h | 1 + utils/src/display_info.cpp | 5 +- 22 files changed, 468 insertions(+), 27 deletions(-) create mode 100644 dm/test/systemtest/display_change_test.cpp diff --git a/dm/include/display_manager_agent.h b/dm/include/display_manager_agent.h index 0d46fde21b..15314296b5 100644 --- a/dm/include/display_manager_agent.h +++ b/dm/include/display_manager_agent.h @@ -28,6 +28,7 @@ public: virtual void NotifyDisplayPowerEvent(DisplayPowerEvent event, EventStatus status) override; virtual void NotifyDisplayStateChanged(DisplayId id, DisplayState state) override; + virtual void OnDisplayChange(const sptr, DisplayChangeEvent) override; }; } } diff --git a/dm/include/display_manager_agent_default.h b/dm/include/display_manager_agent_default.h index 4fbcd8006c..20f0af6d9f 100644 --- a/dm/include/display_manager_agent_default.h +++ b/dm/include/display_manager_agent_default.h @@ -32,7 +32,7 @@ public: void OnScreenChange(const std::vector>&, ScreenChangeEvent) override {}; void OnDisplayCreate(sptr) override {}; void OnDisplayDestroy(DisplayId) override {}; - void OnDisplayChange(sptr, DisplayChangeEvent) override {}; + void OnDisplayChange(const sptr, DisplayChangeEvent) override {}; }; } } diff --git a/dm/src/display.cpp b/dm/src/display.cpp index 20ecf8b6d0..503d1d4171 100644 --- a/dm/src/display.cpp +++ b/dm/src/display.cpp @@ -25,6 +25,7 @@ private: int32_t width_ { 0 }; int32_t height_ { 0 }; uint32_t freshRate_ { 0 }; + ScreenId screenId_ {SCREEN_ID_INVALID}; }; Display::Display(const std::string& name, DisplayInfo* info) @@ -35,6 +36,7 @@ Display::Display(const std::string& name, DisplayInfo* info) pImpl_->width_ = info->width_; pImpl_->height_ = info->height_; pImpl_->freshRate_ = info->freshRate_; + pImpl_->screenId_ = info->screenId_; } DisplayId Display::GetId() const @@ -57,6 +59,11 @@ uint32_t Display::GetFreshRate() const return pImpl_->freshRate_; } +ScreenId Display::GetScreenId() const +{ + return pImpl_->screenId_; +} + void Display::SetWidth(int32_t width) { pImpl_->width_ = width; diff --git a/dm/src/display_manager.cpp b/dm/src/display_manager.cpp index e493de53df..eafbcb04e5 100644 --- a/dm/src/display_manager.cpp +++ b/dm/src/display_manager.cpp @@ -82,7 +82,7 @@ public: } }; - void OnDisplayChange(sptr displayInfo, DisplayChangeEvent event) override + void OnDisplayChange(const sptr displayInfo, DisplayChangeEvent event) override { if (displayInfo == nullptr || displayInfo->id_ == DISPLAY_ID_INVALD) { WLOGFE("OnDisplayChange, displayInfo is invalid."); @@ -94,7 +94,7 @@ public: } WLOGD("OnDisplayChange. display %{public}" PRIu64", event %{public}u", displayInfo->id_, event); for (auto listener : pImpl_->displayListeners_) { - listener->OnChange(displayInfo->id_); + listener->OnChange(displayInfo->id_, event); } }; private: @@ -364,6 +364,16 @@ void DisplayManager::NotifyDisplayStateChanged(DisplayId id, DisplayState state) WLOGFW("callback_ target is not set!"); } +void DisplayManager::NotifyDisplayChangedEvent(const sptr info, DisplayChangeEvent event) +{ + WLOGI("NotifyDisplayChangedEvent event:%{public}u, size:%{public}zu", event, + pImpl_->displayListeners_.size()); + std::lock_guard lock(pImpl_->mutex_); + for (auto& listener : pImpl_->displayListeners_) { + listener->OnChange(info->id_, event); + } +} + bool DisplayManager::WakeUpBegin(PowerStateChangeReason reason) { WLOGFI("WakeUpBegin start, reason:%{public}u", reason); diff --git a/dm/src/display_manager_adapter.cpp b/dm/src/display_manager_adapter.cpp index 611eb4f06b..c3e16c37b5 100644 --- a/dm/src/display_manager_adapter.cpp +++ b/dm/src/display_manager_adapter.cpp @@ -47,14 +47,34 @@ sptr DisplayManagerAdapter::GetDisplayById(DisplayId displayId) { std::lock_guard lock(mutex_); - auto iter = displayMap_.find(displayId); - if (iter != displayMap_.end()) { - return iter->second; + if (!InitDMSProxyLocked()) { + WLOGFE("GetDisplayById: InitDMSProxyLocked failed!"); + return nullptr; } - if (!InitDMSProxyLocked()) { - WLOGFE("displayManagerAdapter::GetDisplayById: InitDMSProxyLocked failed!"); - return nullptr; + auto iter = displayMap_.find(displayId); + if (iter != displayMap_.end()) { + // Update display in map + // should be updated automatically + DisplayInfo displayInfo = displayManagerServiceProxy_->GetDisplayInfoById(displayId); + if (displayInfo.id_ == DISPLAY_ID_INVALD) { + WLOGFE("GetDisplayById: Get invalid displayInfo!"); + return nullptr; + } + sptr display = iter->second; + if (displayInfo.width_ != display->GetWidth()) { + display->SetWidth(displayInfo.width_); + WLOGFI("GetDisplayById: set new width %{public}d", display->GetWidth()); + } + if (displayInfo.height_ != display->GetHeight()) { + display->SetHeight(displayInfo.height_); + WLOGFI("GetDisplayById: set new height %{public}d", display->GetHeight()); + } + if (displayInfo.freshRate_ != display->GetFreshRate()) { + display->SetFreshRate(displayInfo.freshRate_); + WLOGFI("GetDisplayById: set new freshRate %{public}ud", display->GetFreshRate()); + } + return iter->second; } DisplayInfo displayInfo = displayManagerServiceProxy_->GetDisplayInfoById(displayId); sptr display = new Display("", &displayInfo); diff --git a/dm/src/display_manager_agent.cpp b/dm/src/display_manager_agent.cpp index 2a928fc7cf..8d846ce2ce 100644 --- a/dm/src/display_manager_agent.cpp +++ b/dm/src/display_manager_agent.cpp @@ -28,5 +28,10 @@ void DisplayManagerAgent::NotifyDisplayStateChanged(DisplayId id, DisplayState s { SingletonContainer::Get().NotifyDisplayStateChanged(id, state); } + +void DisplayManagerAgent::OnDisplayChange(const sptr info, DisplayChangeEvent event) +{ + SingletonContainer::Get().NotifyDisplayChangedEvent(info, event); +} } // namespace Rosen } // namespace OHOS \ No newline at end of file diff --git a/dm/test/systemtest/BUILD.gn b/dm/test/systemtest/BUILD.gn index dfb83a602b..5ffd32de18 100644 --- a/dm/test/systemtest/BUILD.gn +++ b/dm/test/systemtest/BUILD.gn @@ -19,6 +19,7 @@ group("systemtest") { testonly = true deps = [ + ":dm_display_change_test", ":dm_display_minimal_test", ":dm_display_power_test", ":dm_screen_gamut_test", @@ -48,6 +49,17 @@ ohos_systemtest("dm_display_power_test") { ## SystemTest dm_display_minimal_test }}} +## SystemTest dm_display_change_test {{{ +ohos_systemtest("dm_display_change_test") { + module_out_path = module_out_path + + sources = [ "display_change_test.cpp" ] + + deps = [ ":dm_systemtest_common" ] +} + +## SystemTest dm_display_change_test }}} + ## SystemTest dm_screenshot_test {{{ ohos_systemtest("dm_screenshot_test") { module_out_path = module_out_path diff --git a/dm/test/systemtest/display_change_test.cpp b/dm/test/systemtest/display_change_test.cpp new file mode 100644 index 0000000000..27e17497c6 --- /dev/null +++ b/dm/test/systemtest/display_change_test.cpp @@ -0,0 +1,276 @@ +/* + * Copyright (c) 2022 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 + +#include "display_info.h" +#include "display_manager.h" +#include "screen_manager.h" +#include "screen_manager/rs_screen_mode_info.h" +#include "window_manager_hilog.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0, "DisplayChangeTest"}; + constexpr uint32_t MAX_TIME_WAITING_FOR_CALLBACK = 20; + constexpr uint32_t SLEEP_TIME_IN_US = 1000; // 1ms +} + +class DisplayChangeEventListener : public DisplayManager::IDisplayListener { +public: + virtual void OnCreate(DisplayId displayId) + { + WLOGI("DisplayChangeEventListener::OnCreate displayId=%{public}" PRIu64"", displayId); + } + + virtual void OnDestroy(DisplayId displayId) + { + WLOGI("DisplayChangeEventListener::OnDestroy displayId=%{public}" PRIu64"", displayId); + } + + virtual void OnChange(DisplayId displayId, DisplayChangeEvent event) + { + WLOGI("DisplayChangeEventListener::OnChange displayId=%{public}" PRIu64"", displayId); + isCallbackCalled_ = true; + event_ = event; + displayId_ = displayId; + } + bool isCallbackCalled_ { false }; + DisplayChangeEvent event_ { DisplayChangeEvent::UNKNOWN }; + DisplayId displayId_ { DISPLAY_ID_INVALD }; +}; +using DisplayChangeCallback = std::function, DisplayChangeEvent)>; + +class DisplayChangeTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + bool CheckDisplayChangeEventCallback(bool valueExpected); + bool ScreenSizeEqual(const sptr screen, const sptr curInfo); + bool DisplaySizeEqual(const sptr display, const sptr curInfo); + static DisplayId defaultdisplayId_; + + static sptr listener_; + static inline uint32_t times_ = 0; +}; +DisplayId DisplayChangeTest::defaultdisplayId_ = DISPLAY_ID_INVALD; +sptr DisplayChangeTest::listener_ = new DisplayChangeEventListener(); + +void DisplayChangeTest::SetUpTestCase() +{ + defaultdisplayId_ = DisplayManager::GetInstance().GetDefaultDisplayId(); + if (defaultdisplayId_ == DISPLAY_ID_INVALD) { + WLOGE("DisplayId is invalid!"); + } + if (!DisplayManager::GetInstance().RegisterDisplayListener(listener_)) { + WLOGE("Fail to register display listener"); + } +} + +void DisplayChangeTest::TearDownTestCase() +{ + DisplayManager::GetInstance().UnregisterDisplayListener(listener_); +} + +void DisplayChangeTest::SetUp() +{ + times_ = 0; + listener_->isCallbackCalled_ = false; + listener_->event_ = DisplayChangeEvent::UNKNOWN; + listener_->displayId_ = DISPLAY_ID_INVALD; +} + +void DisplayChangeTest::TearDown() +{ +} + +bool DisplayChangeTest::CheckDisplayChangeEventCallback(bool valueExpected) +{ + WLOGI("CheckDisplayChangeEventCallback in"); + do { + if (listener_->isCallbackCalled_ == valueExpected) { + WLOGI("CheckDisplayChangeEventCallback: get valueExpected %{public}d for display %{public}" PRIu64"", + static_cast(valueExpected), listener_->displayId_); + return true; + } + WLOGI("CheckDisplayChangeEventCallback: wait times %{public}d", times_); + usleep(SLEEP_TIME_IN_US); + ++times_; + } while (times_ <= MAX_TIME_WAITING_FOR_CALLBACK); + return false; +} + +bool DisplayChangeTest::ScreenSizeEqual(const sptr screen, const sptr curInfo) +{ + uint32_t sWidth = screen->GetWidth(); + uint32_t sHeight = screen->GetHeight(); + WLOGI("ScreenSizeEqual: ScreenSize: %{public}u %{public}u, ActiveModeInfoSize: %{public}u %{public}u", + sWidth, sHeight, curInfo->width_, curInfo->height_); + return ((curInfo->width_ == sWidth) && (curInfo->height_ == sHeight)); +} + +bool DisplayChangeTest::DisplaySizeEqual(const sptr display, const sptr curInfo) +{ + uint32_t dWidth = static_cast(display->GetWidth()); + uint32_t dHeight = static_cast(display->GetHeight()); + WLOGI("DisplaySizeEqual:: DisplaySize: %{public}u %{public}u, ActiveModeInfoSize: %{public}u %{public}u", + dWidth, dHeight, curInfo->width_, curInfo->height_); + return ((curInfo->width_ == dWidth) && (curInfo->height_ == dHeight)); +} + +namespace { +/** + * @tc.name: RegisterDisplayChangeListener01 + * @tc.desc: Register displayChangeListener with valid listener and check return true + * @tc.type: FUNC + */ +HWTEST_F(DisplayChangeTest, RegisterDisplayChangeListener01, Function | SmallTest | Level2) +{ + sptr listener = new DisplayChangeEventListener(); + bool ret = DisplayManager::GetInstance().RegisterDisplayListener(listener); + ASSERT_EQ(true, ret); +} + +/** + * @tc.name: RegisterDisplayChangeListener02 + * @tc.desc: Register displayChangeListener with nullptr and check return false + * @tc.type: FUNC + */ +HWTEST_F(DisplayChangeTest, RegisterDisplayChangeListener02, Function | SmallTest | Level2) +{ + bool ret = DisplayManager::GetInstance().RegisterDisplayListener(nullptr); + ASSERT_EQ(false, ret); +} + +/** + * @tc.name: UnregisterDisplayChangeListener01 + * @tc.desc: Unregister displayChangeListener with valid listener and check return true + * @tc.type: FUNC + */ +HWTEST_F(DisplayChangeTest, UnregisterDisplayChangeListener01, Function | SmallTest | Level2) +{ + sptr listener = new DisplayChangeEventListener(); + DisplayManager::GetInstance().RegisterDisplayListener(listener); + bool ret = DisplayManager::GetInstance().UnregisterDisplayListener(listener); + ASSERT_EQ(true, ret); +} + +/** + * @tc.name: UnregisterDisplayChangeListener02 + * @tc.desc: Register displayChangeListener with nullptr and check return false + * @tc.type: FUNC + */ +HWTEST_F(DisplayChangeTest, UnregisterDisplayChangeListener02, Function | SmallTest | Level2) +{ + bool ret = DisplayManager::GetInstance().UnregisterDisplayListener(nullptr); + ASSERT_EQ(false, ret); +} + +/** + * @tc.name: UnregisterDisplayChangeListener03 + * @tc.desc: Register displayChangeListener with invalid listener and check return false + * @tc.type: FUNC + */ +HWTEST_F(DisplayChangeTest, UnregisterDisplayChangeListener03, Function | SmallTest | Level2) +{ + sptr listener = new DisplayChangeEventListener(); + bool ret = DisplayManager::GetInstance().UnregisterDisplayListener(listener); + ASSERT_EQ(false, ret); +} + +/** + * @tc.name: CheckDisplayStateChange01 + * @tc.desc: DisplayState not change if screen sets same mode + * @tc.type: FUNC + */ +HWTEST_F(DisplayChangeTest, CheckDisplayStateChange01, Function | SmallTest | Level2) +{ + WLOGFI("CheckDisplayStateChange01"); + sptr defaultDisplay = DisplayManager::GetInstance().GetDisplayById(defaultdisplayId_); + ScreenId screenId = defaultDisplay->GetScreenId(); + sptr screen = ScreenManager::GetInstance().GetScreenById(screenId); + ASSERT_NE(nullptr, screen); + uint32_t usedModeIdx = screen->GetModeId(); + screen->SetScreenActiveMode(usedModeIdx); + WLOGFI("SetScreenActiveMode: %{public}u", usedModeIdx); + ASSERT_EQ(false, CheckDisplayChangeEventCallback(true)); +} + +/** + * @tc.name: CheckDisplayStateChange02 + * @tc.desc: DisplayState changes if screen sets different mode + * @tc.type: FUNC + */ +HWTEST_F(DisplayChangeTest, CheckDisplayStateChange02, Function | SmallTest | Level2) +{ + WLOGFI("CheckDisplayStateChange02"); + sptr defaultDisplay = DisplayManager::GetInstance().GetDisplayById(defaultdisplayId_); + ScreenId screenId = defaultDisplay->GetScreenId(); + sptr screen = ScreenManager::GetInstance().GetScreenById(screenId); + ASSERT_NE(nullptr, screen); + auto modes = screen->GetSupportedModes(); + uint32_t usedModeIdx = screen->GetModeId(); + WLOGFI("usedModeIdx / SupportMode size: %{public}u %{public}d", usedModeIdx, static_cast(modes.size())); + + for (uint32_t modeIdx = 0; modeIdx < modes.size(); modeIdx++) { + if (modeIdx != usedModeIdx) { + screen->SetScreenActiveMode(modeIdx); + WLOGFI("SetScreenActiveMode: %{public}u", modeIdx); + ASSERT_EQ(true, CheckDisplayChangeEventCallback(true)); + WLOGFI("CheckDisplayChangeEventCallback: true"); + } + } + screen->SetScreenActiveMode(usedModeIdx); + WLOGFI("SetScreenActiveMode: %{public}u", usedModeIdx); +} + +/** + * @tc.name: CheckDisplaySizeChange01 + * @tc.desc: Check display size change as screen mode set if screen sets another mode + * @tc.type: FUNC + */ +HWTEST_F(DisplayChangeTest, CheckDisplaySizeChange01, Function | MediumTest | Level2) +{ + WLOGFI("CheckDisplaySizeChange01"); + sptr defaultDisplay = DisplayManager::GetInstance().GetDisplayById(defaultdisplayId_); + ScreenId screenId = defaultDisplay->GetScreenId(); + sptr screen = ScreenManager::GetInstance().GetScreenById(screenId); + ASSERT_NE(nullptr, screen); + auto modes = screen->GetSupportedModes(); + uint32_t usedModeIdx = screen->GetModeId(); + WLOGFI("usedModeIdx / SupportMode size: %{public}u %{public}d", usedModeIdx, static_cast(modes.size())); + + for (uint32_t modeIdx = 0; modeIdx < modes.size(); modeIdx++) { + if (modeIdx != usedModeIdx) { + screen->SetScreenActiveMode(modeIdx); + WLOGFI("SetScreenActiveMode: %{public}u -> %{public}u", usedModeIdx, modeIdx); + ASSERT_EQ(true, ScreenSizeEqual(screen, modes[modeIdx])); + ASSERT_EQ(true, CheckDisplayChangeEventCallback(true)); + defaultDisplay = DisplayManager::GetInstance().GetDisplayById(defaultdisplayId_); + ASSERT_EQ(true, DisplaySizeEqual(defaultDisplay, modes[modeIdx])); + } + } + screen->SetScreenActiveMode(usedModeIdx); + WLOGFI("SetScreenActiveMode: %{public}u", usedModeIdx); +} +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/dmserver/include/abstract_display_controller.h b/dmserver/include/abstract_display_controller.h index 7ae2297c1a..9cbb9eb88b 100644 --- a/dmserver/include/abstract_display_controller.h +++ b/dmserver/include/abstract_display_controller.h @@ -45,9 +45,12 @@ private: void OnAbstractScreenConnect(sptr absScreen); void OnAbstractScreenDisconnect(sptr absScreen); void OnAbstractScreenChange(sptr absScreen, DisplayChangeEvent event); + void ProcessDisplayUpdateRotation(sptr absScreen); + void ProcessDisplaySizeChange(sptr absScreen); void BindAloneScreenLocked(sptr absScreen); void AddScreenToMirrorLocked(sptr group, sptr realAbsScreen); void ProcessScreenDisconnected(sptr absScreen, sptr screenGroup); + bool UpdateDisplaySize(sptr absDisplay, sptr info); std::recursive_mutex& mutex_; std::atomic displayCount_ { 0 }; diff --git a/dmserver/include/abstract_screen_controller.h b/dmserver/include/abstract_screen_controller.h index 2e1441e884..72183e9606 100644 --- a/dmserver/include/abstract_screen_controller.h +++ b/dmserver/include/abstract_screen_controller.h @@ -81,6 +81,7 @@ private: bool CheckScreenInScreenGroup(sptr newScreen) const; sptr AddAsFirstScreenLocked(sptr newScreen); sptr AddAsSuccedentScreenLocked(sptr newScreen); + void ProcessScreenModeChanged(ScreenId rsScreenId); std::recursive_mutex& mutex_; OHOS::Rosen::RSInterfaces& rsInterface_; diff --git a/dmserver/src/abstract_display.cpp b/dmserver/src/abstract_display.cpp index 0b48597c47..7f8334a95f 100644 --- a/dmserver/src/abstract_display.cpp +++ b/dmserver/src/abstract_display.cpp @@ -148,6 +148,7 @@ const sptr AbstractDisplay::ConvertToDisplayInfo() const displayInfo->height_ = height_; displayInfo->id_ = id_; displayInfo->freshRate_ = freshRate_; + displayInfo->screenId_ = screenId_; return displayInfo; } } // namespace OHOS::Rosen \ No newline at end of file diff --git a/dmserver/src/abstract_display_controller.cpp b/dmserver/src/abstract_display_controller.cpp index 2625596e15..4f1f827551 100644 --- a/dmserver/src/abstract_display_controller.cpp +++ b/dmserver/src/abstract_display_controller.cpp @@ -168,10 +168,22 @@ void AbstractDisplayController::ProcessScreenDisconnected( void AbstractDisplayController::OnAbstractScreenChange(sptr absScreen, DisplayChangeEvent event) { - if (event != DisplayChangeEvent::UPDATE_ROTATION) { - WLOGFE("unknown display event: %{public}u", event); + if (absScreen == nullptr) { + WLOGE("OnAbstractScreenChanged::the information of the screen is wrong"); return; } + WLOGI("screen changes. id:%{public}" PRIu64"", absScreen->dmsId_); + + if (event == DisplayChangeEvent::UPDATE_ROTATION) { + ProcessDisplayUpdateRotation(absScreen); + } + if (event == DisplayChangeEvent::DISPLAY_SIZE_CHANGED) { + ProcessDisplaySizeChange(absScreen); + } +} + +void AbstractDisplayController::ProcessDisplayUpdateRotation(sptr absScreen) +{ sptr abstractDisplay = nullptr; std::lock_guard lock(mutex_); auto iter = abstractDisplayMap_.begin(); @@ -214,6 +226,43 @@ void AbstractDisplayController::OnAbstractScreenChange(sptr absS } } +void AbstractDisplayController::ProcessDisplaySizeChange(sptr absScreen) +{ + sptr info = absScreen->GetActiveScreenMode(); + if (info == nullptr) { + WLOGE("cannot get active screen info."); + return; + } + std::lock_guard lock(mutex_); + for (auto iter = abstractDisplayMap_.begin(); iter != abstractDisplayMap_.end(); iter++) { + sptr absDisplay = iter->second; + if (absDisplay->GetAbstractScreenId() != absScreen->dmsId_) { + continue; + } + if (UpdateDisplaySize(absDisplay, info)) { + WLOGFI("Notify display size change"); + DisplayManagerService::GetInstance().NotifyDisplayStateChange( + iter->first, DisplayStateChangeType::SIZE_CHANGE); + DisplayManagerAgentController::GetInstance().OnDisplayChange( + absDisplay->ConvertToDisplayInfo(), DisplayChangeEvent::DISPLAY_SIZE_CHANGED); + } + } +} + +bool AbstractDisplayController::UpdateDisplaySize(sptr absDisplay, sptr info) +{ + if (info->height_ == absDisplay->GetHeight() && info->width_ == absDisplay->GetWidth()) { + WLOGI("keep display size. display:%{public}" PRIu64"", absDisplay->GetId()); + return false; + } + std::lock_guard lock(mutex_); + absDisplay->SetHeight(info->height_); + absDisplay->SetWidth(info->width_); + WLOGI("update display size. id %{public}" PRIu64", size: %{public}d %{public}d", + absDisplay->GetId(), absDisplay->GetWidth(), absDisplay->GetHeight()); + return true; +} + void AbstractDisplayController::BindAloneScreenLocked(sptr realAbsScreen) { ScreenId defaultScreenId = abstractScreenController_->GetDefaultAbstractScreenId(); diff --git a/dmserver/src/abstract_screen_controller.cpp b/dmserver/src/abstract_screen_controller.cpp index b75c92ec64..04ff90f29c 100644 --- a/dmserver/src/abstract_screen_controller.cpp +++ b/dmserver/src/abstract_screen_controller.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include "display_manager_agent_controller.h" #include "display_manager_service.h" @@ -235,6 +236,35 @@ void AbstractScreenController::OnRsScreenConnectionChange(ScreenId rsScreenId, S } } +void AbstractScreenController::ProcessScreenModeChanged(ScreenId rsScreenId) +{ + auto iter = rs2DmsScreenIdMap_.find(rsScreenId); + if (iter == rs2DmsScreenIdMap_.end()) { + WLOGE("ProcessScreenModeChanged: screenId=%{public}" PRIu64" is not in rs2DmsScreenIdMap_", rsScreenId); + return; + } + WLOGFD("ProcessScreenModeChanged: process screen info changes"); + ScreenId dmsScreenId = iter->second; + auto dmsScreenMapIter = dmsScreenMap_.find(dmsScreenId); + if (dmsScreenMapIter == dmsScreenMap_.end()) { + WLOGE("ProcessScreenModeChanged: no dms screen is found, rsscreenId=%{public}" PRIu64"", rsScreenId); + return; + } + sptr absScreen = dmsScreenMapIter->second; + int32_t activeModeId = rsInterface_.GetScreenActiveMode(rsScreenId).GetScreenModeId(); + if (activeModeId < 0 || activeModeId >= absScreen->modes_.size()) { + WLOGE("activeModeId exceed, screenId=%{public}" PRIu64", activeModeId:%{public}d/%{public}u", + rsScreenId, activeModeId, static_cast(absScreen->modes_.size())); + return; + } + absScreen->activeIdx_ = activeModeId; + if (abstractScreenCallback_ != nullptr) { + abstractScreenCallback_->onChange_(absScreen, DisplayChangeEvent::DISPLAY_SIZE_CHANGED); + } + DisplayManagerAgentController::GetInstance().OnScreenChange( + absScreen->ConvertToScreenInfo(), ScreenChangeEvent::CHANGE_MODE); +} + void AbstractScreenController::ProcessScreenDisconnected(ScreenId rsScreenId) { WLOGI("disconnect screen, screenId=%{public}" PRIu64"", rsScreenId); @@ -557,7 +587,20 @@ bool AbstractScreenController::SetScreenActiveMode(ScreenId screenId, uint32_t m WLOGFE("SetScreenActiveMode: Get AbstractScreen failed"); return false; } + std::lock_guard lock(mutex_); + uint32_t usedModeId = screen->activeIdx_; screen->activeIdx_ = modeId; + // add thread to process mode change sync event + // should be called by OnRsScreenChange if rs implement corresponding event callback + if (usedModeId != modeId) { + WLOGI("SetScreenActiveMode: modeId: %{public}u -> %{public}u", usedModeId, modeId); + auto func = [=]() { + ProcessScreenModeChanged(screenId); + return; + }; + std::thread thread(func); + thread.detach(); + } return true; } diff --git a/dmserver/src/display_manager_agent_controller.cpp b/dmserver/src/display_manager_agent_controller.cpp index 366524306c..0f666e86a0 100644 --- a/dmserver/src/display_manager_agent_controller.cpp +++ b/dmserver/src/display_manager_agent_controller.cpp @@ -135,7 +135,8 @@ void DisplayManagerAgentController::OnDisplayDestroy(DisplayId displayId) } } -void DisplayManagerAgentController::OnDisplayChange(sptr displayInfo, DisplayChangeEvent screenChangeEvent) +void DisplayManagerAgentController::OnDisplayChange( + sptr displayInfo, DisplayChangeEvent displayChangeEvent) { auto agents = dmAgentContainer_.GetAgentsByType(DisplayManagerAgentType::DISPLAY_EVENT_LISTENER); if (agents.empty()) { @@ -143,7 +144,7 @@ void DisplayManagerAgentController::OnDisplayChange(sptr displayInf } WLOGFI("OnDisplayChange"); for (auto& agent : agents) { - agent->OnDisplayChange(displayInfo, screenChangeEvent); + agent->OnDisplayChange(displayInfo, displayChangeEvent); } } } diff --git a/dmserver/src/display_manager_service.cpp b/dmserver/src/display_manager_service.cpp index c4d635a635..5da3533332 100644 --- a/dmserver/src/display_manager_service.cpp +++ b/dmserver/src/display_manager_service.cpp @@ -92,12 +92,16 @@ DisplayId DisplayManagerService::GetDefaultDisplayId() DisplayInfo DisplayManagerService::GetDisplayInfoById(DisplayId displayId) { DisplayInfo displayInfo; - ScreenId screenId = GetScreenIdFromDisplayId(displayId); - auto screenModeInfo = abstractDisplayController_->GetScreenActiveMode(screenId); + sptr display = GetDisplayByDisplayId(displayId); + if (display == nullptr) { + WLOGFE("GetDisplayById: Get invalid display!"); + return displayInfo; + } displayInfo.id_ = displayId; - displayInfo.width_ = screenModeInfo.GetScreenWidth(); - displayInfo.height_ = screenModeInfo.GetScreenHeight(); - displayInfo.freshRate_ = screenModeInfo.GetScreenFreshRate(); + displayInfo.width_ = display->GetWidth(); + displayInfo.height_ = display->GetHeight(); + displayInfo.freshRate_ = display->GetFreshRate(); + displayInfo.screenId_ = display->GetAbstractScreenId(); return displayInfo; } diff --git a/interfaces/innerkits/dm/display.h b/interfaces/innerkits/dm/display.h index 2c6b6b38f1..a71df54436 100644 --- a/interfaces/innerkits/dm/display.h +++ b/interfaces/innerkits/dm/display.h @@ -17,12 +17,10 @@ #define FOUNDATION_DM_DISPLAY_H #include -#include +#include "dm_common.h" namespace OHOS::Rosen { class DisplayInfo; -using DisplayId = uint64_t; -static constexpr DisplayId DISPLAY_ID_INVALD = -1ULL; typedef enum DisplayType { DEFAULT = 0, @@ -37,6 +35,7 @@ public: int32_t GetWidth() const; int32_t GetHeight() const; uint32_t GetFreshRate() const; + ScreenId GetScreenId() const; float GetVirtualPixelRatio() const; void SetId(DisplayId displayId); diff --git a/interfaces/innerkits/dm/display_manager.h b/interfaces/innerkits/dm/display_manager.h index b337c804c2..9bc7384b9c 100644 --- a/interfaces/innerkits/dm/display_manager.h +++ b/interfaces/innerkits/dm/display_manager.h @@ -35,7 +35,7 @@ public: public: virtual void OnCreate(DisplayId) = 0; virtual void OnDestroy(DisplayId) = 0; - virtual void OnChange(DisplayId) = 0; + virtual void OnChange(DisplayId, DisplayChangeEvent) = 0; }; std::vector> GetAllDisplays(); @@ -64,6 +64,7 @@ public: uint32_t GetScreenBrightness(uint64_t screenId) const; void NotifyDisplayEvent(DisplayEvent event); constexpr static int32_t MAX_RESOLUTION_SIZE_SCREENSHOT = 3840; // max resolution, 4K + private: DisplayManager(); ~DisplayManager(); @@ -75,6 +76,7 @@ private: void NotifyDisplayPowerEvent(DisplayPowerEvent event, EventStatus status); void NotifyDisplayStateChanged(DisplayId id, DisplayState state); + void NotifyDisplayChangedEvent(const sptr info, DisplayChangeEvent event); }; } // namespace OHOS::Rosen diff --git a/interfaces/innerkits/dm/dm_common.h b/interfaces/innerkits/dm/dm_common.h index 0c8e240bc7..08180577e5 100644 --- a/interfaces/innerkits/dm/dm_common.h +++ b/interfaces/innerkits/dm/dm_common.h @@ -20,6 +20,11 @@ namespace OHOS { namespace Rosen { +using DisplayId = uint64_t; +using ScreenId = uint64_t; +static constexpr DisplayId DISPLAY_ID_INVALD = -1ULL; +static constexpr ScreenId SCREEN_ID_INVALID = -1ULL; + enum class PowerStateChangeReason : uint32_t { POWER_BUTTON, }; @@ -83,6 +88,7 @@ enum class ScreenChangeEvent : uint32_t { REMOVE_FROM_GROUP, CHANGE_GROUP, UPDATE_ROTATION, + CHANGE_MODE, }; enum class Rotation : uint32_t { @@ -95,6 +101,7 @@ enum class Rotation : uint32_t { enum class DisplayChangeEvent : uint32_t { UPDATE_ROTATION, DISPLAY_SIZE_CHANGED, + UNKNOWN, }; } } diff --git a/interfaces/innerkits/dm/screen.h b/interfaces/innerkits/dm/screen.h index ec8f3b5b3c..f6660d0a5f 100644 --- a/interfaces/innerkits/dm/screen.h +++ b/interfaces/innerkits/dm/screen.h @@ -19,7 +19,6 @@ #include #include -#include #include #include @@ -27,8 +26,6 @@ namespace OHOS::Rosen { class ScreenInfo; -using ScreenId = uint64_t; -static constexpr ScreenId SCREEN_ID_INVALID = -1ULL; struct Point { int32_t posX_; diff --git a/utils/include/display_change_listener.h b/utils/include/display_change_listener.h index 2efe753402..60e5dc466c 100644 --- a/utils/include/display_change_listener.h +++ b/utils/include/display_change_listener.h @@ -24,6 +24,7 @@ enum class DisplayStateChangeType : uint32_t { BEFORE_SUSPEND, BEFORE_UNLOCK, UPDATE_ROTATION, + SIZE_CHANGE, }; class IDisplayChangeListener : public RefBase { public: diff --git a/utils/include/display_info.h b/utils/include/display_info.h index a642e4763a..0aab10100d 100644 --- a/utils/include/display_info.h +++ b/utils/include/display_info.h @@ -37,6 +37,7 @@ public: int32_t width_ { 0 }; int32_t height_ { 0 }; uint32_t freshRate_ { 0 }; + ScreenId screenId_ { SCREEN_ID_INVALID }; float xDpi_ { 0.0 }; float yDpi_ { 0.0 }; Rotation rotation_ { Rotation::ROTATION_0 }; diff --git a/utils/src/display_info.cpp b/utils/src/display_info.cpp index e9cd101158..0ff79f3179 100644 --- a/utils/src/display_info.cpp +++ b/utils/src/display_info.cpp @@ -23,6 +23,7 @@ void DisplayInfo::Update(DisplayInfo* info) width_ = info->width_; height_ = info->height_; freshRate_ = info->freshRate_; + screenId_ = info->screenId_; xDpi_ = info->xDpi_; yDpi_ = info->yDpi_; rotation_ = info->rotation_; @@ -32,7 +33,7 @@ bool DisplayInfo::Marshalling(Parcel &parcel) const { return parcel.WriteUint64(id_) && parcel.WriteUint32(type_) && parcel.WriteInt32(width_) && parcel.WriteInt32(height_) && - parcel.WriteUint32(freshRate_) && + parcel.WriteUint32(freshRate_) && parcel.WriteUint64(screenId_) && parcel.WriteFloat(xDpi_) && parcel.WriteFloat(yDpi_) && parcel.WriteUint32(static_cast(rotation_)); } @@ -47,7 +48,7 @@ DisplayInfo *DisplayInfo::Unmarshalling(Parcel &parcel) uint32_t rotation; bool res = parcel.ReadUint64(displayInfo->id_) && parcel.ReadUint32(type) && parcel.ReadInt32(displayInfo->width_) && parcel.ReadInt32(displayInfo->height_) && - parcel.ReadUint32(displayInfo->freshRate_) && + parcel.ReadUint32(displayInfo->freshRate_) && parcel.ReadUint64(displayInfo->screenId_) && parcel.ReadFloat(displayInfo->xDpi_) && parcel.ReadFloat(displayInfo->yDpi_) && parcel.ReadUint32(rotation); if (!res) {