diff --git a/dm/include/display_manager_adapter.h b/dm/include/display_manager_adapter.h index 47ce2d3b..8568ea10 100644 --- a/dm/include/display_manager_adapter.h +++ b/dm/include/display_manager_adapter.h @@ -74,7 +74,8 @@ private: class ScreenManagerAdapter : public BaseAdapter { WM_DECLARE_SINGLE_INSTANCE(ScreenManagerAdapter); public: - virtual ScreenId CreateVirtualScreen(VirtualScreenOption option); + virtual ScreenId CreateVirtualScreen(VirtualScreenOption option, + const sptr& displayManagerAgent); virtual DMError DestroyVirtualScreen(ScreenId screenId); virtual DMError SetVirtualScreenSurface(ScreenId screenId, sptr surface); virtual bool SetScreenPowerForAll(ScreenPowerState state, PowerStateChangeReason reason); diff --git a/dm/include/zidl/display_manager_agent_interface.h b/dm/include/zidl/display_manager_agent_interface.h index e4bb73c4..69b682d3 100644 --- a/dm/include/zidl/display_manager_agent_interface.h +++ b/dm/include/zidl/display_manager_agent_interface.h @@ -28,6 +28,7 @@ enum class DisplayManagerAgentType : uint32_t { DISPLAY_STATE_LISTENER, SCREEN_EVENT_LISTENER, DISPLAY_EVENT_LISTENER, + VIRTUAL_SCREEN_DIED_LISTENER, }; class IDisplayManagerAgent : public IRemoteBroker { diff --git a/dm/src/display_manager_adapter.cpp b/dm/src/display_manager_adapter.cpp index a3c3fb2b..0394c0c7 100644 --- a/dm/src/display_manager_adapter.cpp +++ b/dm/src/display_manager_adapter.cpp @@ -100,12 +100,13 @@ DMError ScreenManagerAdapter::SetScreenColorTransform(ScreenId screenId) return displayManagerServiceProxy_->SetScreenColorTransform(screenId); } -ScreenId ScreenManagerAdapter::CreateVirtualScreen(VirtualScreenOption option) +ScreenId ScreenManagerAdapter::CreateVirtualScreen(VirtualScreenOption option, + const sptr& displayManagerAgent) { INIT_PROXY_CHECK_RETURN(SCREEN_ID_INVALID); WLOGFI("DisplayManagerAdapter::CreateVirtualScreen"); - return displayManagerServiceProxy_->CreateVirtualScreen(option); + return displayManagerServiceProxy_->CreateVirtualScreen(option, displayManagerAgent->AsObject()); } DMError ScreenManagerAdapter::DestroyVirtualScreen(ScreenId screenId) diff --git a/dm/src/screen_manager.cpp b/dm/src/screen_manager.cpp index df2f7f18..87ad1447 100644 --- a/dm/src/screen_manager.cpp +++ b/dm/src/screen_manager.cpp @@ -39,6 +39,7 @@ public: bool UnregisterScreenListener(sptr listener); bool RegisterScreenGroupListener(sptr listener); bool UnregisterScreenGroupListener(sptr listener); + ScreenId CreateVirtualScreen(VirtualScreenOption option); sptr GetScreen(ScreenId screenId); sptr GetScreenGroup(ScreenId screenId); std::vector> GetAllScreens(); @@ -57,6 +58,7 @@ private: std::recursive_mutex mutex_; std::set> screenListeners_; std::set> screenGroupListeners_; + sptr virtualScreenAgent_ = nullptr; }; class ScreenManager::Impl::ScreenManagerListener : public DisplayManagerAgentDefault { @@ -139,6 +141,7 @@ public: private: sptr pImpl_; }; + WM_IMPLEMENT_SINGLE_INSTANCE(ScreenManager) ScreenManager::ScreenManager() @@ -395,7 +398,16 @@ void ScreenManager::RemoveVirtualScreenFromGroup(std::vector screens) ScreenId ScreenManager::CreateVirtualScreen(VirtualScreenOption option) { - return SingletonContainer::Get().CreateVirtualScreen(option); + return pImpl_->CreateVirtualScreen(option); +} + +ScreenId ScreenManager::Impl::CreateVirtualScreen(VirtualScreenOption option) +{ + // After the process creating the virtual screen is killed, DMS needs to delete the virtual screen + if (virtualScreenAgent_ == nullptr) { + virtualScreenAgent_ = new DisplayManagerAgentDefault(); + } + return SingletonContainer::Get().CreateVirtualScreen(option, virtualScreenAgent_); } DMError ScreenManager::DestroyVirtualScreen(ScreenId screenId) diff --git a/dm/test/systemtest/screen_manager_test.cpp b/dm/test/systemtest/screen_manager_test.cpp index 3611e755..1e8b1825 100644 --- a/dm/test/systemtest/screen_manager_test.cpp +++ b/dm/test/systemtest/screen_manager_test.cpp @@ -234,6 +234,7 @@ HWTEST_F(ScreenManagerTest, ScreenManager01, Function | MediumTest | Level2) DisplayTestUtils utils; ASSERT_TRUE(utils.CreateSurface()); defaultOption_.surface_ = utils.psurface_; + defaultOption_.isForShot_ = false; ScreenId virtualScreenId = ScreenManager::GetInstance().CreateVirtualScreen(defaultOption_); ASSERT_NE(SCREEN_ID_INVALID, virtualScreenId); ASSERT_EQ(DMError::DM_OK, ScreenManager::GetInstance().DestroyVirtualScreen(virtualScreenId)); @@ -249,6 +250,7 @@ HWTEST_F(ScreenManagerTest, ScreenManager02, Function | MediumTest | Level2) DisplayTestUtils utils; ASSERT_TRUE(utils.CreateSurface()); defaultOption_.surface_ = utils.psurface_; + defaultOption_.isForShot_ = false; ScreenId virtualScreenId = ScreenManager::GetInstance().CreateVirtualScreen(defaultOption_); std::vector mirrorIds; mirrorIds.push_back(virtualScreenId); @@ -265,9 +267,10 @@ HWTEST_F(ScreenManagerTest, ScreenManager02, Function | MediumTest | Level2) HWTEST_F(ScreenManagerTest, ScreenManager03, Function | MediumTest | Level2) { DisplayTestUtils utils; - ASSERT_TRUE(utils.CreateSurface()); - defaultOption_.surface_ = utils.psurface_; + defaultOption_.isForShot_ = false; for (uint32_t i = 0; i < execTimes_; i++) { + ASSERT_TRUE(utils.CreateSurface()); + defaultOption_.surface_ = utils.psurface_; ScreenId virtualScreenId = ScreenManager::GetInstance().CreateVirtualScreen(defaultOption_); ASSERT_NE(SCREEN_ID_INVALID, virtualScreenId); ASSERT_EQ(DMError::DM_OK, ScreenManager::GetInstance().DestroyVirtualScreen(virtualScreenId)); @@ -282,9 +285,10 @@ HWTEST_F(ScreenManagerTest, ScreenManager03, Function | MediumTest | Level2) HWTEST_F(ScreenManagerTest, ScreenManager04, Function | MediumTest | Level2) { DisplayTestUtils utils; - ASSERT_TRUE(utils.CreateSurface()); - defaultOption_.surface_ = utils.psurface_; + defaultOption_.isForShot_ = false; for (uint32_t i = 0; i < execTimes_; i++) { + ASSERT_TRUE(utils.CreateSurface()); + defaultOption_.surface_ = utils.psurface_; ScreenId virtualScreenId = ScreenManager::GetInstance().CreateVirtualScreen(defaultOption_); std::vector mirrorIds; mirrorIds.push_back(virtualScreenId); @@ -305,6 +309,7 @@ HWTEST_F(ScreenManagerTest, ScreenManager05, Function | MediumTest | Level2) utils.SetDefaultWH(defaultDisplay_); ASSERT_TRUE(utils.CreateSurface()); defaultOption_.surface_ = utils.psurface_; + defaultOption_.isForShot_ = true; ScreenId virtualScreenId = ScreenManager::GetInstance().CreateVirtualScreen(defaultOption_); ASSERT_NE(SCREEN_ID_INVALID, virtualScreenId); @@ -337,6 +342,7 @@ HWTEST_F(ScreenManagerTest, ScreenManager06, Function | MediumTest | Level2) DisplayTestUtils utils; utils.SetDefaultWH(defaultDisplay_); defaultOption_.surface_ = nullptr; + defaultOption_.isForShot_ = true; ScreenId virtualScreenId = ScreenManager::GetInstance().CreateVirtualScreen(defaultOption_); ASSERT_NE(SCREEN_ID_INVALID, virtualScreenId); @@ -715,6 +721,23 @@ HWTEST_F(ScreenManagerTest, ScreenManager16, Function | MediumTest | Level2) ASSERT_EQ(static_cast(display->GetOrientation()), static_cast(Orientation::UNSPECIFIED)); ScreenManager::GetInstance().UnregisterScreenListener(screenListener); } + +/** + * @tc.name: ScreenManager17 + * @tc.desc: Create VirtualScreen for 10 times but do not destroy it + * @tc.type: FUNC + */ +HWTEST_F(ScreenManagerTest, ScreenManager17, Function | MediumTest | Level2) +{ + DisplayTestUtils utils; + defaultOption_.isForShot_ = false; + for (uint32_t i = 0; i < execTimes_; i++) { + ASSERT_TRUE(utils.CreateSurface()); + defaultOption_.surface_ = utils.psurface_; + ScreenId virtualScreenId = ScreenManager::GetInstance().CreateVirtualScreen(defaultOption_); + ASSERT_NE(SCREEN_ID_INVALID, virtualScreenId); + } +} } } // namespace Rosen } // namespace OHOS diff --git a/dm/test/unittest/mock_display_manager_adapter.h b/dm/test/unittest/mock_display_manager_adapter.h index 2a33b8f0..c5cef055 100644 --- a/dm/test/unittest/mock_display_manager_adapter.h +++ b/dm/test/unittest/mock_display_manager_adapter.h @@ -50,7 +50,8 @@ public: MOCK_METHOD2(UnregisterDisplayManagerAgent, bool(const sptr& displayManagerAgent, DisplayManagerAgentType type)); MOCK_METHOD2(RequestRotation, bool(ScreenId screenId, Rotation rotation)); - MOCK_METHOD1(CreateVirtualScreen, ScreenId(VirtualScreenOption option)); + MOCK_METHOD2(CreateVirtualScreen, ScreenId(VirtualScreenOption option, + const sptr& displayManagerAgent)); MOCK_METHOD1(DestroyVirtualScreen, DMError(ScreenId screenId)); MOCK_METHOD2(SetVirtualScreenSurface, DMError(ScreenId screenId, sptr surface)); MOCK_METHOD1(GetScreenGroupInfoById, sptr(ScreenId screenId)); diff --git a/dm/test/unittest/screen_manager_test.cpp b/dm/test/unittest/screen_manager_test.cpp index 3e19390d..72113de3 100644 --- a/dm/test/unittest/screen_manager_test.cpp +++ b/dm/test/unittest/screen_manager_test.cpp @@ -60,7 +60,7 @@ HWTEST_F(ScreenManagerTest, CreateAndDestory01, Function | SmallTest | Level1) VirtualScreenOption wrongOption = {defaultName_, defaultWidth_, defaultHeight_, defaultDensity_, nullptr, defaultFlags_}; std::unique_ptr m = std::make_unique(); - EXPECT_CALL(m->Mock(), CreateVirtualScreen(_)).Times(1).WillOnce(Return(SCREEN_ID_INVALID)); + EXPECT_CALL(m->Mock(), CreateVirtualScreen(_, _)).Times(1).WillOnce(Return(SCREEN_ID_INVALID)); EXPECT_CALL(m->Mock(), DestroyVirtualScreen(_)).Times(1).WillOnce(Return(DMError::DM_ERROR_INVALID_PARAM)); ScreenId id = ScreenManager::GetInstance().CreateVirtualScreen(wrongOption); DMError ret = ScreenManager::GetInstance().DestroyVirtualScreen(id); @@ -81,7 +81,7 @@ HWTEST_F(ScreenManagerTest, CreateAndDestory02, Function | SmallTest | Level1) defaultDensity_, utils.psurface_, defaultFlags_}; ScreenId validId = 0; std::unique_ptr m = std::make_unique(); - EXPECT_CALL(m->Mock(), CreateVirtualScreen(_)).Times(1).WillOnce(Return(validId)); + EXPECT_CALL(m->Mock(), CreateVirtualScreen(_, _)).Times(1).WillOnce(Return(validId)); EXPECT_CALL(m->Mock(), DestroyVirtualScreen(_)).Times(1).WillOnce(Return(DMError::DM_OK)); ScreenId id = ScreenManager::GetInstance().CreateVirtualScreen(defaultOption); DMError ret = ScreenManager::GetInstance().DestroyVirtualScreen(id); @@ -103,7 +103,7 @@ HWTEST_F(ScreenManagerTest, MakeExpand_001, Function | SmallTest | Level1) ScreenId validId = 0; // default srceenId(0) ScreenId virtualScreenId = 1; // VirtualScreen is the second screen(1) std::unique_ptr m = std::make_unique(); - EXPECT_CALL(m->Mock(), CreateVirtualScreen(_)).Times(1).WillOnce(Return(virtualScreenId)); + EXPECT_CALL(m->Mock(), CreateVirtualScreen(_, _)).Times(1).WillOnce(Return(virtualScreenId)); EXPECT_CALL(m->Mock(), DestroyVirtualScreen(_)).Times(1).WillOnce(Return(DMError::DM_OK)); EXPECT_CALL(m->Mock(), MakeExpand(_, _)).Times(1).WillOnce(Return(0)); ScreenId vScreenId = ScreenManager::GetInstance().CreateVirtualScreen(defaultOption); @@ -141,7 +141,7 @@ HWTEST_F(ScreenManagerTest, SetSurface01, Function | SmallTest | Level1) defaultDensity_, nullptr, defaultFlags_}; ScreenId validId = 0; std::unique_ptr m = std::make_unique(); - EXPECT_CALL(m->Mock(), CreateVirtualScreen(_)).Times(1).WillOnce(Return(validId)); + EXPECT_CALL(m->Mock(), CreateVirtualScreen(_, _)).Times(1).WillOnce(Return(validId)); EXPECT_CALL(m->Mock(), SetVirtualScreenSurface(_, _)).Times(1).WillOnce(Return(DMError::DM_OK)); EXPECT_CALL(m->Mock(), DestroyVirtualScreen(_)).Times(1).WillOnce(Return(DMError::DM_OK)); ScreenId id = ScreenManager::GetInstance().CreateVirtualScreen(defaultOption); @@ -164,7 +164,7 @@ HWTEST_F(ScreenManagerTest, SetSurface02, Function | SmallTest | Level1) VirtualScreenOption defaultOption = {defaultName_, defaultWidth_, defaultHeight_, defaultDensity_, nullptr, defaultFlags_}; std::unique_ptr m = std::make_unique(); - EXPECT_CALL(m->Mock(), CreateVirtualScreen(_)).Times(1).WillOnce(Return(SCREEN_ID_INVALID)); + EXPECT_CALL(m->Mock(), CreateVirtualScreen(_, _)).Times(1).WillOnce(Return(SCREEN_ID_INVALID)); EXPECT_CALL(m->Mock(), SetVirtualScreenSurface(_, _)).Times(1).WillOnce(Return(DMError::DM_ERROR_INVALID_PARAM)); EXPECT_CALL(m->Mock(), DestroyVirtualScreen(_)).Times(1).WillOnce(Return(DMError::DM_ERROR_INVALID_PARAM)); ScreenId id = ScreenManager::GetInstance().CreateVirtualScreen(defaultOption); diff --git a/dmserver/include/abstract_screen_controller.h b/dmserver/include/abstract_screen_controller.h index 81c508ab..94617dcb 100644 --- a/dmserver/include/abstract_screen_controller.h +++ b/dmserver/include/abstract_screen_controller.h @@ -25,8 +25,10 @@ #include #include "abstract_screen.h" +#include "display_manager_agent_controller.h" #include "dm_common.h" #include "screen.h" +#include "zidl/display_manager_agent_interface.h" namespace OHOS::Rosen { class AbstractScreenController : public RefBase { @@ -54,7 +56,7 @@ public: ScreenId ConvertToRsScreenId(ScreenId dmsScreenId) const; ScreenId ConvertToDmsScreenId(ScreenId rsScreenId) const; void RegisterAbstractScreenCallback(sptr cb); - ScreenId CreateVirtualScreen(VirtualScreenOption option); + ScreenId CreateVirtualScreen(VirtualScreenOption option, const sptr& displayManagerAgent); DMError DestroyVirtualScreen(ScreenId screenId); DMError SetVirtualScreenSurface(ScreenId screenId, sptr surface); bool SetOrientation(ScreenId screenId, Orientation orientation); @@ -64,6 +66,7 @@ public: void UpdateRSTree(ScreenId dmsScreenId, std::shared_ptr& surfaceNode, bool isAdd); bool MakeMirror(ScreenId, std::vector screens); bool MakeExpand(std::vector screenIds, std::vector startPoints); + void SetShotScreen(ScreenId mainScreenId, std::vector shotScreenIds); void RemoveVirtualScreenFromGroup(std::vector screens); void DumpScreenInfo() const; bool SetScreenPowerForAll(ScreenPowerState state, PowerStateChangeReason reason) const; @@ -80,6 +83,8 @@ public: private: void RegisterRsScreenConnectionChangeListener(); void OnRsScreenConnectionChange(ScreenId rsScreenId, ScreenEvent screenEvent); + bool OnRemoteDied(const sptr& agent); + bool RegisterVirtualScreenAgent(const sptr& displayManagerAgent); void ProcessScreenConnected(ScreenId rsScreenId); sptr InitAndGetScreen(ScreenId rsScreenId); void ProcessScreenDisconnected(ScreenId rsScreenId); @@ -129,6 +134,8 @@ private: ScreenIdManager screenIdManager_; std::map> dmsScreenMap_; std::map> dmsScreenGroupMap_; + std::map> displayNodeMap_; + std::map, std::vector> screenAgentMap_; sptr abstractScreenCallback_; std::shared_ptr controllerHandler_; }; diff --git a/dmserver/include/display_manager_agent_controller.h b/dmserver/include/display_manager_agent_controller.h index 9761a04e..ca723ac3 100644 --- a/dmserver/include/display_manager_agent_controller.h +++ b/dmserver/include/display_manager_agent_controller.h @@ -25,11 +25,13 @@ namespace OHOS { namespace Rosen { class DisplayManagerAgentController { WM_DECLARE_SINGLE_INSTANCE_BASE(DisplayManagerAgentController) +using VirtualScreenDestroyCallback = std::function)>; public: bool RegisterDisplayManagerAgent(const sptr& displayManagerAgent, DisplayManagerAgentType type); bool UnregisterDisplayManagerAgent(const sptr& displayManagerAgent, DisplayManagerAgentType type); + bool SetRemoveAgentCallback(const VirtualScreenDestroyCallback& callback, DisplayManagerAgentType type); bool NotifyDisplayPowerEvent(DisplayPowerEvent event, EventStatus status); bool NotifyDisplayStateChanged(DisplayId id, DisplayState state); diff --git a/dmserver/include/display_manager_interface.h b/dmserver/include/display_manager_interface.h index 14c12cf8..f926b5b6 100644 --- a/dmserver/include/display_manager_interface.h +++ b/dmserver/include/display_manager_interface.h @@ -76,7 +76,8 @@ public: virtual sptr GetDisplayInfoById(DisplayId displayId) = 0; virtual sptr GetDisplayInfoByScreen(ScreenId screenId) = 0; - virtual ScreenId CreateVirtualScreen(VirtualScreenOption option) = 0; + virtual ScreenId CreateVirtualScreen(VirtualScreenOption option, + const sptr& displayManagerAgent) = 0; virtual DMError DestroyVirtualScreen(ScreenId screenId) = 0; virtual DMError SetVirtualScreenSurface(ScreenId screenId, sptr surface) = 0; virtual bool SetOrientation(ScreenId screenId, Orientation orientation) = 0; diff --git a/dmserver/include/display_manager_proxy.h b/dmserver/include/display_manager_proxy.h index 8eb28a51..3748bd47 100644 --- a/dmserver/include/display_manager_proxy.h +++ b/dmserver/include/display_manager_proxy.h @@ -35,7 +35,8 @@ public: sptr GetDisplayInfoById(DisplayId displayId) override; sptr GetDisplayInfoByScreen(ScreenId screenId) override; - ScreenId CreateVirtualScreen(VirtualScreenOption option) override; + ScreenId CreateVirtualScreen(VirtualScreenOption option, + const sptr& displayManagerAgent) override; DMError DestroyVirtualScreen(ScreenId screenId) override; DMError SetVirtualScreenSurface(ScreenId screenId, sptr surface) override; bool SetOrientation(ScreenId screenId, Orientation orientation) override; diff --git a/dmserver/include/display_manager_service.h b/dmserver/include/display_manager_service.h index eb270b0e..4c2e83aa 100644 --- a/dmserver/include/display_manager_service.h +++ b/dmserver/include/display_manager_service.h @@ -41,7 +41,8 @@ WM_DECLARE_SINGLE_INSTANCE_BASE(DisplayManagerService); public: void OnStart() override; void OnStop() override; - ScreenId CreateVirtualScreen(VirtualScreenOption option) override; + ScreenId CreateVirtualScreen(VirtualScreenOption option, + const sptr& displayManagerAgent) override; DMError DestroyVirtualScreen(ScreenId screenId) override; DMError SetVirtualScreenSurface(ScreenId screenId, sptr surface) override; @@ -93,7 +94,6 @@ private: ~DisplayManagerService() = default; bool Init(); void NotifyDisplayStateChange(DisplayId id, DisplayStateChangeType type); - void SetShotScreen(ScreenId mainScreenId, std::vector shotScreenIds); ScreenId GetScreenIdByDisplayId(DisplayId displayId) const; std::shared_ptr GetRSDisplayNodeByDisplayId(DisplayId displayId) const; @@ -102,7 +102,6 @@ private: sptr abstractDisplayController_; sptr abstractScreenController_; sptr displayPowerController_; - std::map> displayNodeMap_; sptr displayChangeListener_; }; } // namespace OHOS::Rosen diff --git a/dmserver/src/abstract_screen_controller.cpp b/dmserver/src/abstract_screen_controller.cpp index 310cbebf..e0a0a8c9 100644 --- a/dmserver/src/abstract_screen_controller.cpp +++ b/dmserver/src/abstract_screen_controller.cpp @@ -63,6 +63,12 @@ void AbstractScreenController::RegisterRsScreenConnectionChangeListener() // posk task after 50 ms. controllerHandler_->PostTask(task, 50, AppExecFwk::EventQueue::Priority::HIGH); } + bool callbackRegister = DisplayManagerAgentController::GetInstance().SetRemoveAgentCallback( + std::bind(&AbstractScreenController::OnRemoteDied, this, std::placeholders::_1), + DisplayManagerAgentType::VIRTUAL_SCREEN_DIED_LISTENER); + if (!callbackRegister) { + WLOGFE("virtualScreen callback registered failed"); + } } std::vector AbstractScreenController::GetAllScreenIds() const @@ -460,7 +466,15 @@ sptr AbstractScreenController::AddAsSuccedentScreenLocked(s return screenGroup; } -ScreenId AbstractScreenController::CreateVirtualScreen(VirtualScreenOption option) +bool AbstractScreenController::RegisterVirtualScreenAgent(const sptr& displayManagerAgent) +{ + return DisplayManagerAgentController::GetInstance().RegisterDisplayManagerAgent( + iface_cast(displayManagerAgent), + DisplayManagerAgentType::VIRTUAL_SCREEN_DIED_LISTENER); +} + +ScreenId AbstractScreenController::CreateVirtualScreen(VirtualScreenOption option, + const sptr& displayManagerAgent) { ScreenId rsId = rsInterface_.CreateVirtualScreen(option.name_, option.width_, option.height_, option.surface_, SCREEN_ID_INVALID, option.flags_); @@ -468,7 +482,16 @@ ScreenId AbstractScreenController::CreateVirtualScreen(VirtualScreenOption optio if (rsId == SCREEN_ID_INVALID) { return SCREEN_ID_INVALID; } + std::vector virtualScreenIds; std::lock_guard lock(mutex_); + std::map, std::vector>::iterator agIter = screenAgentMap_.find(displayManagerAgent); + if (agIter == screenAgentMap_.end()) { + if (!RegisterVirtualScreenAgent(displayManagerAgent)) { + return SCREEN_ID_INVALID; + } + } else { + virtualScreenIds = screenAgentMap_[displayManagerAgent]; + } ScreenId dmsScreenId = SCREEN_ID_INVALID; if (!screenIdManager_.ConvertToDmsScreenId(rsId, dmsScreenId)) { dmsScreenId = screenIdManager_.CreateAndGetNewScreenId(rsId); @@ -498,6 +521,8 @@ ScreenId AbstractScreenController::CreateVirtualScreen(VirtualScreenOption optio } else { WLOGFI("id: %{public}" PRIu64" appears in screenIdManager_. ", rsId); } + virtualScreenIds.emplace_back(dmsScreenId); + screenAgentMap_[displayManagerAgent] = virtualScreenIds; return dmsScreenId; } @@ -507,13 +532,45 @@ DMError AbstractScreenController::DestroyVirtualScreen(ScreenId screenId) std::lock_guard lock(mutex_); ScreenId rsScreenId = SCREEN_ID_INVALID; screenIdManager_.ConvertToRsScreenId(screenId, rsScreenId); + + sptr displayManagerAgent = nullptr; + bool agentFound = false; + for (auto &agentIter : screenAgentMap_) { + for (auto iter = agentIter.second.begin(); iter != agentIter.second.end(); iter++) { + if (*iter == screenId) { + iter = agentIter.second.erase(iter); + agentFound = true; + break; + } + } + if (agentFound) { + break; + } + } + + std::map>::iterator iter = displayNodeMap_.find(rsScreenId); + if (iter == displayNodeMap_.end()) { + WLOGFI("displayNode is nullptr"); + } else { + displayNodeMap_[rsScreenId]->RemoveFromTree(); + WLOGFI("displayNode remove from tree rsScreenId: %{public}" PRIu64"", rsScreenId); + displayNodeMap_.erase(rsScreenId); + auto transactionProxy = RSTransactionProxy::GetInstance(); + if (transactionProxy != nullptr) { + transactionProxy->FlushImplicitTransaction(); + } + } + if (rsScreenId != SCREEN_ID_INVALID && GetAbstractScreen(screenId) != nullptr) { ProcessScreenDisconnected(rsScreenId); } screenIdManager_.DeleteScreenId(screenId); - if (rsScreenId != SCREEN_ID_INVALID) { - rsInterface_.RemoveVirtualScreen(rsScreenId); + + if (rsScreenId == SCREEN_ID_INVALID) { + WLOGFE("DestroyVirtualScreen: No corresponding rsScreenId"); + return DMError::DM_ERROR_INVALID_PARAM; } + rsInterface_.RemoveVirtualScreen(rsScreenId); WLOGFI("DumpScreenInfo after Destroy VirtualScreen"); DumpScreenInfo(); return DMError::DM_OK; @@ -814,6 +871,34 @@ bool AbstractScreenController::MakeExpand(std::vector screenIds, std:: return true; } +void AbstractScreenController::SetShotScreen(ScreenId mainScreenId, std::vector shotScreenIds) +{ + WLOGFI("SetShotScreen. mainScreenId: %{public}" PRIu64"", mainScreenId); + if (shotScreenIds.empty()) { + WLOGFI("shotScreenIds is empty"); + return; + } + std::shared_ptr displayNode = GetRSDisplayNodeByScreenId(mainScreenId); + if (displayNode == nullptr) { + WLOGFE("SetShotScreen error, cannot get DisplayNode"); + return; + } + NodeId nodeId = displayNode->GetId(); + WLOGI("SetShotScreen, mainScreen nodeId:%{public}" PRIu64"", nodeId); + for (ScreenId shotScreenId : shotScreenIds) { + shotScreenId = ConvertToRsScreenId(shotScreenId); + if (shotScreenId == SCREEN_ID_INVALID) { + continue; + } + struct RSDisplayNodeConfig config = {shotScreenId, true, nodeId}; + displayNodeMap_[shotScreenId] = RSDisplayNode::Create(config); + } + auto transactionProxy = RSTransactionProxy::GetInstance(); + if (transactionProxy != nullptr) { + transactionProxy->FlushImplicitTransaction(); + } +} + void AbstractScreenController::RemoveVirtualScreenFromGroup(std::vector screens) { if (screens.empty()) { @@ -841,6 +926,26 @@ void AbstractScreenController::RemoveVirtualScreenFromGroup(std::vector& agent) +{ + if (agent == nullptr) { + return false; + } + std::map, std::vector>::iterator agentIter = screenAgentMap_.find(agent); + if (agentIter != screenAgentMap_.end()) { + while (screenAgentMap_[agent].size() > 0) { + auto diedId = screenAgentMap_[agent][0]; + WLOGI("destroy screenId in OnRemoteDied: %{public}" PRIu64"", diedId); + DMError res = DestroyVirtualScreen(diedId); + if (res != DMError::DM_OK) { + WLOGE("destroy failed in OnRemoteDied: %{public}" PRIu64"", diedId); + } + } + screenAgentMap_.erase(agent); + } + return true; +} + void AbstractScreenController::DumpScreenInfo() const { std::lock_guard lock(mutex_); diff --git a/dmserver/src/display_manager_agent_controller.cpp b/dmserver/src/display_manager_agent_controller.cpp index 82e4b453..a206c53e 100644 --- a/dmserver/src/display_manager_agent_controller.cpp +++ b/dmserver/src/display_manager_agent_controller.cpp @@ -175,5 +175,11 @@ void DisplayManagerAgentController::OnDisplayChange( agent->OnDisplayChange(displayInfo, displayChangeEvent); } } + +bool DisplayManagerAgentController::SetRemoveAgentCallback(const VirtualScreenDestroyCallback& callback, + DisplayManagerAgentType type) +{ + return dmAgentContainer_.SetRemoveAgentCallback(callback, type); +} } } \ No newline at end of file diff --git a/dmserver/src/display_manager_proxy.cpp b/dmserver/src/display_manager_proxy.cpp index 96d82406..48c0429e 100644 --- a/dmserver/src/display_manager_proxy.cpp +++ b/dmserver/src/display_manager_proxy.cpp @@ -115,7 +115,8 @@ sptr DisplayManagerProxy::GetDisplayInfoByScreen(ScreenId screenId) return info; } -ScreenId DisplayManagerProxy::CreateVirtualScreen(VirtualScreenOption virtualOption) +ScreenId DisplayManagerProxy::CreateVirtualScreen(VirtualScreenOption virtualOption, + const sptr& displayManagerAgent) { sptr remote = Remote(); if (remote == nullptr) { @@ -141,6 +142,10 @@ ScreenId DisplayManagerProxy::CreateVirtualScreen(VirtualScreenOption virtualOpt WLOGFW("CreateVirtualScreen: surface is nullptr"); res = res && data.WriteBool(false); } + if (displayManagerAgent != nullptr) { + res = res && + data.WriteRemoteObject(displayManagerAgent); + } if (!res) { WLOGFE("Write data failed"); return SCREEN_ID_INVALID; diff --git a/dmserver/src/display_manager_service.cpp b/dmserver/src/display_manager_service.cpp index 9befafdf..e65adf1f 100644 --- a/dmserver/src/display_manager_service.cpp +++ b/dmserver/src/display_manager_service.cpp @@ -116,11 +116,12 @@ sptr DisplayManagerService::GetDisplayInfoByScreen(ScreenId screenI } return display->ConvertToDisplayInfo(); } - -ScreenId DisplayManagerService::CreateVirtualScreen(VirtualScreenOption option) + +ScreenId DisplayManagerService::CreateVirtualScreen(VirtualScreenOption option, + const sptr& displayManagerAgent) { WM_SCOPED_TRACE("dms:CreateVirtualScreen(%s)", option.name_.c_str()); - ScreenId screenId = abstractScreenController_->CreateVirtualScreen(option); + ScreenId screenId = abstractScreenController_->CreateVirtualScreen(option, displayManagerAgent); CHECK_SCREEN_AND_RETURN(SCREEN_ID_INVALID); WLOGFI("DumpScreenInfo after Create VirtualScreen"); @@ -134,19 +135,6 @@ DMError DisplayManagerService::DestroyVirtualScreen(ScreenId screenId) CHECK_SCREEN_AND_RETURN(DMError::DM_ERROR_INVALID_PARAM); WM_SCOPED_TRACE("dms:DestroyVirtualScreen(%" PRIu64")", screenId); - auto rsScreenId = abstractScreenController_->ConvertToRsScreenId(screenId); - std::map>::iterator iter = displayNodeMap_.find(rsScreenId); - if (iter == displayNodeMap_.end()) { - WLOGFE("DisplayManagerService: displayNode is nullptr"); - return abstractScreenController_->DestroyVirtualScreen(screenId); - } - displayNodeMap_[rsScreenId]->RemoveFromTree(); - WLOGFE("DisplayManagerService: displayNode remove from tree"); - displayNodeMap_.erase(rsScreenId); - auto transactionProxy = RSTransactionProxy::GetInstance(); - if (transactionProxy != nullptr) { - transactionProxy->FlushImplicitTransaction(); - } return abstractScreenController_->DestroyVirtualScreen(screenId); } @@ -345,34 +333,6 @@ std::shared_ptr DisplayManagerService::GetRSDisplayNodeByDisplayI return abstractScreenController_->GetRSDisplayNodeByScreenId(screenId); } -void DisplayManagerService::SetShotScreen(ScreenId mainScreenId, std::vector shotScreenIds) -{ - WLOGFI("SetShotScreen. mainScreenId: %{public}" PRIu64"", mainScreenId); - if (shotScreenIds.empty()) { - WLOGFI("shotScreenIds is empty"); - return; - } - std::shared_ptr displayNode = abstractScreenController_->GetRSDisplayNodeByScreenId(mainScreenId); - if (displayNode == nullptr) { - WLOGFE("SetShotScreen error, cannot get DisplayNode"); - return; - } - NodeId nodeId = displayNode->GetId(); - WLOGI("SetShotScreen, mainScreen nodeId:%{public}" PRIu64"", nodeId); - for (ScreenId shotScreenId : shotScreenIds) { - shotScreenId = abstractScreenController_->ConvertToRsScreenId(shotScreenId); - if (shotScreenId == INVALID_SCREEN_ID) { - continue; - } - struct RSDisplayNodeConfig config = {shotScreenId, true, nodeId}; - displayNodeMap_[shotScreenId] = RSDisplayNode::Create(config); - } - auto transactionProxy = RSTransactionProxy::GetInstance(); - if (transactionProxy != nullptr) { - transactionProxy->FlushImplicitTransaction(); - } -} - ScreenId DisplayManagerService::MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenIds) { WLOGFI("MakeMirror. mainScreenId :%{public}" PRIu64"", mainScreenId); @@ -390,7 +350,7 @@ ScreenId DisplayManagerService::MakeMirror(ScreenId mainScreenId, std::vectorSetShotScreen(mainScreenId, shotScreenIds); WM_SCOPED_TRACE("dms:MakeMirror"); if (!allMirrorScreenIds.empty() && !abstractScreenController_->MakeMirror(mainScreenId, allMirrorScreenIds)) { WLOGFE("make mirror failed."); @@ -481,7 +441,7 @@ ScreenId DisplayManagerService::MakeExpand(std::vector expandScreenIds if (iter != allExpandScreenIds.end()) { allExpandScreenIds.erase(iter); } - SetShotScreen(defaultScreenId, shotScreenIds); + abstractScreenController_->SetShotScreen(defaultScreenId, shotScreenIds); WM_SCOPED_TRACE("dms:MakeExpand"); if (!allExpandScreenIds.empty() && !abstractScreenController_->MakeExpand(allExpandScreenIds, startPoints)) { WLOGFE("make expand failed."); diff --git a/dmserver/src/display_manager_stub.cpp b/dmserver/src/display_manager_stub.cpp index e7a520e8..aa7db267 100644 --- a/dmserver/src/display_manager_stub.cpp +++ b/dmserver/src/display_manager_stub.cpp @@ -68,6 +68,7 @@ int32_t DisplayManagerStub::OnRemoteRequest(uint32_t code, MessageParcel &data, sptr bp = iface_cast(surfaceObject); surface = Surface::CreateSurfaceAsProducer(bp); } + sptr virtualScreenAgent = data.ReadRemoteObject(); VirtualScreenOption option = { .name_ = name, .width_ = width, @@ -77,7 +78,7 @@ int32_t DisplayManagerStub::OnRemoteRequest(uint32_t code, MessageParcel &data, .flags_ = flags, .isForShot_ = isForShot }; - ScreenId screenId = CreateVirtualScreen(option); + ScreenId screenId = CreateVirtualScreen(option, virtualScreenAgent); reply.WriteUint64(static_cast(screenId)); break; } diff --git a/interfaces/innerkits/dm/dm_common.h b/interfaces/innerkits/dm/dm_common.h index 95ed87b9..04530d9a 100644 --- a/interfaces/innerkits/dm/dm_common.h +++ b/interfaces/innerkits/dm/dm_common.h @@ -65,6 +65,7 @@ enum class DMError : int32_t { DM_ERROR_INVALID_MODE_ID = 160, DM_ERROR_WRITE_DATA_FAILED = 170, DM_ERROR_RENDER_SERVICE_FAILED = 180, + DM_ERROR_UNREGISTER_AGENT_FAILED = 190, DM_ERROR_UNKNOWN, }; using DisplayStateCallback = std::function; diff --git a/utils/include/client_agent_container.h b/utils/include/client_agent_container.h index 2d349376..14fcec3b 100644 --- a/utils/include/client_agent_container.h +++ b/utils/include/client_agent_container.h @@ -21,22 +21,25 @@ #include #include "agent_death_recipient.h" #include "window_manager_hilog.h" +#include "zidl/display_manager_agent_interface.h" namespace OHOS { namespace Rosen { template class ClientAgentContainer { +using DestroyCallback = std::function)>; public: ClientAgentContainer(); virtual ~ClientAgentContainer() = default; bool RegisterAgent(const sptr& agent, T2 type); bool UnregisterAgent(const sptr& agent, T2 type); + bool SetRemoveAgentCallback(const DestroyCallback& callback, T2 type); std::set> GetAgentsByType(T2 type); private: void RemoveAgent(const sptr& remoteObject); - bool UnregisterAgentLocked(std::set>& agents, const sptr& agent); + sptr UnregisterAgentLocked(std::set>& agents, const sptr& agent); static constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "ClientAgentContainer"}; @@ -53,6 +56,7 @@ private: std::recursive_mutex mutex_; std::map>> agentMap_; + std::map callbackMap_; sptr deathRecipient_; }; @@ -65,7 +69,6 @@ bool ClientAgentContainer::RegisterAgent(const sptr& agent, T2 type) { std::lock_guard lock(mutex_); agentMap_[type].insert(agent); - WLOGFI("agent registered type:%{public}u", type); if (deathRecipient_ == nullptr || !agent->AsObject()->AddDeathRecipient(deathRecipient_)) { WLOGFI("failed to add death recipient"); } @@ -81,9 +84,20 @@ bool ClientAgentContainer::UnregisterAgent(const sptr& agent, T2 typ return false; } auto& agents = agentMap_.at(type); - bool ret = UnregisterAgentLocked(agents, agent->AsObject()); - agent->AsObject()->RemoveDeathRecipient(deathRecipient_); - return ret; + WLOGFI("UnregisterAgent: agent: %{public}p in ClientAgentContainer", agent->AsObject().GetRefPtr()); + auto ret = UnregisterAgentLocked(agents, agent->AsObject()); + if (ret != nullptr) { + agent->AsObject()->RemoveDeathRecipient(deathRecipient_); + } + return true; +} + +template +bool ClientAgentContainer::SetRemoveAgentCallback(const DestroyCallback& callback, T2 type) +{ + callbackMap_[type] = callback; + WLOG_I("ClientAgentContainer callback registered type:%{public}u", type); + return true; } template @@ -98,17 +112,17 @@ std::set> ClientAgentContainer::GetAgentsByType(T2 type) } template -bool ClientAgentContainer::UnregisterAgentLocked(std::set>& agents, +sptr ClientAgentContainer::UnregisterAgentLocked(std::set>& agents, const sptr& agent) { auto iter = std::find_if(agents.begin(), agents.end(), finder_t(agent)); if (iter == agents.end()) { WLOGFW("could not find this agent"); - return false; + return nullptr; } + auto res = *iter; agents.erase(iter); - WLOGFI("agent unregistered"); - return true; + return res; } template @@ -116,8 +130,14 @@ void ClientAgentContainer::RemoveAgent(const sptr& remote { WLOGFI("RemoveAgent"); std::lock_guard lock(mutex_); + DestroyCallback removeAgentCallback = nullptr; for (auto& elem : agentMap_) { - if (UnregisterAgentLocked(elem.second, remoteObject)) { + auto agent = UnregisterAgentLocked(elem.second, remoteObject); + if (agent != nullptr) { + if (callbackMap_[elem.first] != nullptr) { + removeAgentCallback = callbackMap_[elem.first]; + removeAgentCallback(remoteObject); + } break; } } diff --git a/wmserver/src/input_window_monitor.cpp b/wmserver/src/input_window_monitor.cpp index 5d2ffbad..c976767c 100644 --- a/wmserver/src/input_window_monitor.cpp +++ b/wmserver/src/input_window_monitor.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-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 diff --git a/wmserver/src/window_controller.cpp b/wmserver/src/window_controller.cpp index a9448dfc..cf317351 100644 --- a/wmserver/src/window_controller.cpp +++ b/wmserver/src/window_controller.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-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 diff --git a/wmserver/src/window_manager_proxy.cpp b/wmserver/src/window_manager_proxy.cpp index 6c92098d..40f13280 100644 --- a/wmserver/src/window_manager_proxy.cpp +++ b/wmserver/src/window_manager_proxy.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-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 diff --git a/wmserver/src/window_manager_service.cpp b/wmserver/src/window_manager_service.cpp index db5d78bd..6400fa27 100644 --- a/wmserver/src/window_manager_service.cpp +++ b/wmserver/src/window_manager_service.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-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 diff --git a/wmserver/src/window_node.cpp b/wmserver/src/window_node.cpp index 34e32918..4bd8ce44 100644 --- a/wmserver/src/window_node.cpp +++ b/wmserver/src/window_node.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-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 diff --git a/wmserver/src/window_node_container.cpp b/wmserver/src/window_node_container.cpp index cbac0739..8cb44369 100644 --- a/wmserver/src/window_node_container.cpp +++ b/wmserver/src/window_node_container.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-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 diff --git a/wmserver/src/window_zorder_policy.cpp b/wmserver/src/window_zorder_policy.cpp index 65451a4a..8b68172c 100644 --- a/wmserver/src/window_zorder_policy.cpp +++ b/wmserver/src/window_zorder_policy.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-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