diff --git a/dmserver/include/abstract_screen.h b/dmserver/include/abstract_screen.h index 8137727f61b26bd936857abeda37c90d4cc25c19..cdce4a91d30f2376054a11e23277ed47288808f1 100644 --- a/dmserver/include/abstract_screen.h +++ b/dmserver/include/abstract_screen.h @@ -18,6 +18,7 @@ #include +#include #include #include #include @@ -66,19 +67,20 @@ public: class AbstractScreenGroup : public AbstractScreen { public: - AbstractScreenGroup(ScreenId dmsId, ScreenId rsId); + AbstractScreenGroup(ScreenId dmsId, ScreenId rsId, ScreenCombination combination); AbstractScreenGroup() = delete; ~AbstractScreenGroup(); - bool AddChild(ScreenCombination combination, sptr& dmsScreen, Point& startPoint); - bool AddChild(ScreenCombination combination, - std::vector>& dmsScreens, - std::vector& startPoints); + bool AddChild(sptr& dmsScreen, Point& startPoint); + bool AddChildren(std::vector>& dmsScreens, std::vector& startPoints); + bool RemoveChild(sptr& dmsScreen); std::vector> GetChildren() const; std::vector GetChildrenPosition() const; + size_t GetChildCount() const; ScreenCombination combination_ { ScreenCombination::SCREEN_ALONE }; - std::vector> children_; +private: + std::map, Point>> abstractScreenMap_; }; } // namespace OHOS::Rosen #endif // FOUNDATION_DMSERVER_ABSTRACT_SCREEN_H \ No newline at end of file diff --git a/dmserver/include/abstract_screen_controller.h b/dmserver/include/abstract_screen_controller.h index b4d7b5388a25420e228bda0fe293e0b168be7bef..dd8b09ef9f3664c9129123654ab45dddec27dd43 100644 --- a/dmserver/include/abstract_screen_controller.h +++ b/dmserver/include/abstract_screen_controller.h @@ -55,10 +55,12 @@ public: private: void OnRsScreenChange(ScreenId rsScreenId, ScreenEvent screenEvent); + void ProcessScreenDisconnected(ScreenId rsScreenId); bool FillAbstractScreen(sptr& absScreen, ScreenId rsScreenId); sptr AddToGroupLocked(sptr newScreen); + sptr RemoveFromGroupLocked(sptr newScreen); sptr AddAsFirstScreenLocked(sptr newScreen); - void AddAsSuccedentScreenLocked(sptr newScreen); + sptr AddAsSuccedentScreenLocked(sptr newScreen); std::recursive_mutex& mutex_; OHOS::Rosen::RSInterfaces *rsInterface_; diff --git a/dmserver/src/abstract_screen.cpp b/dmserver/src/abstract_screen.cpp index 983c1d503dd0d0d4afd73e9dedaaf227a9610c58..04507517f9f56a77189cdd0dc434bb1d2d936ecc 100644 --- a/dmserver/src/abstract_screen.cpp +++ b/dmserver/src/abstract_screen.cpp @@ -21,8 +21,9 @@ namespace OHOS::Rosen { namespace { - constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0, "AbstractScreen"}; + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0, "AbstractScreenGroup"}; } + AbstractScreen::AbstractScreen(ScreenId dmsId, ScreenId rsId) : dmsId_(dmsId), rsId_(rsId) { @@ -46,7 +47,8 @@ sptr AbstractScreen::GetGroup() const return DisplayManagerService::GetInstance().GetAbstractScreenController()->GetAbstractScreenGroup(groupDmsId_); } -AbstractScreenGroup::AbstractScreenGroup(ScreenId dmsId, ScreenId rsId) : AbstractScreen(dmsId, rsId) +AbstractScreenGroup::AbstractScreenGroup(ScreenId dmsId, ScreenId rsId, ScreenCombination combination) + : AbstractScreen(dmsId, rsId), combination_(combination) { type_ = ScreenType::UNDEFINE; } @@ -54,11 +56,22 @@ AbstractScreenGroup::AbstractScreenGroup(ScreenId dmsId, ScreenId rsId) : Abstra AbstractScreenGroup::~AbstractScreenGroup() { rsDisplayNode_ = nullptr; - children_.clear(); + abstractScreenMap_.clear(); } -bool AbstractScreenGroup::AddChild(ScreenCombination type, sptr& dmsScreen, Point& startPoint) -{ +bool AbstractScreenGroup::AddChild(sptr& dmsScreen, Point& startPoint) +{ + if (dmsScreen == nullptr) { + WLOGE("AddChild, dmsScreen is nullptr."); + return false; + } + ScreenId screenId = dmsScreen->dmsId_; + auto iter = abstractScreenMap_.find(screenId); + if (iter != abstractScreenMap_.end()) { + WLOGE("AddChild, abstractScreenMap_ has dmsScreen:%{public}" PRIu64"", screenId); + return false; + } + struct RSDisplayNodeConfig config; switch (combination_) { case ScreenCombination::SCREEN_ALONE: @@ -77,27 +90,59 @@ bool AbstractScreenGroup::AddChild(ScreenCombination type, sptr& WLOGE("fail to add child. create rsDisplayNode fail!"); return false; } - children_.push_back(dmsScreen); dmsScreen->rsDisplayNode_ = rsDisplayNode; + abstractScreenMap_.insert(std::make_pair(screenId, std::make_pair(dmsScreen, startPoint))); return true; } -bool AbstractScreenGroup::AddChild(ScreenCombination type, - std::vector>& dmsScreens, - std::vector& startPoints) +bool AbstractScreenGroup::AddChildren(std::vector>& dmsScreens, std::vector& startPoints) { - return true; + size_t size = dmsScreens.size(); + if (size != startPoints.size()) { + WLOGE("AddChildren, unequal size."); + return false; + } + bool res = true; + for (size_t i = 0; i < size; i++) { + res &= AddChild(dmsScreens[i], startPoints[i]); + } + return res; +} + +bool AbstractScreenGroup::RemoveChild(sptr& dmsScreen) +{ + if (dmsScreen == nullptr) { + WLOGE("RemoveChild, dmsScreen is nullptr."); + return false; + } + ScreenId screenId = dmsScreen->dmsId_; + bool res = abstractScreenMap_.erase(screenId); + if (abstractScreenMap_.size() == 1) { + combination_ = ScreenCombination::SCREEN_ALONE; + } + return res; } std::vector> AbstractScreenGroup::GetChildren() const { - std::vector> tmp; - return tmp; + std::vector> res; + for (auto iter = abstractScreenMap_.begin(); iter != abstractScreenMap_.end(); iter++) { + res.push_back(iter->second.first); + } + return res; } std::vector AbstractScreenGroup::GetChildrenPosition() const { - std::vector tmp; - return tmp; + std::vector res; + for (auto iter = abstractScreenMap_.begin(); iter != abstractScreenMap_.end(); iter++) { + res.push_back(iter->second.second); + } + return res; +} + +size_t AbstractScreenGroup::GetChildCount() const +{ + return abstractScreenMap_.size(); } } // namespace OHOS::Rosen \ No newline at end of file diff --git a/dmserver/src/abstract_screen_controller.cpp b/dmserver/src/abstract_screen_controller.cpp index 733fd25c2e48f7d718dac35046a77d0ed80bf7b9..f99a1c987f28c5121b4688cd0c5d1419fcc260b3 100644 --- a/dmserver/src/abstract_screen_controller.cpp +++ b/dmserver/src/abstract_screen_controller.cpp @@ -42,7 +42,7 @@ void AbstractScreenController::Init() WLOGFD("screen controller init"); dmsScreenCount_ = 0; if (rsInterface_ == nullptr) { - WLOGFE("rsInterface is null, init failed"); + WLOGFE("rsInterface_ is nullptr, init failed"); } else { rsInterface_->SetScreenChangeCallback( std::bind(&AbstractScreenController::OnRsScreenChange, this, std::placeholders::_1, std::placeholders::_2)); @@ -59,7 +59,7 @@ sptr AbstractScreenController::GetAbstractScreen(ScreenId dmsScr { auto iter = dmsScreenMap_.find(dmsScreenId); if (iter == dmsScreenMap_.end()) { - WLOGE("didnot find screen:%{public}" PRIu64"", dmsScreenId); + WLOGI("didnot find screen:%{public}" PRIu64"", dmsScreenId); return nullptr; } sptr screen = iter->second; @@ -127,12 +127,40 @@ void AbstractScreenController::OnRsScreenChange(ScreenId rsScreenId, ScreenEvent WLOGE("reconnect screen, screenId=%{public}" PRIu64"", rsScreenId); } } else if (screenEvent == ScreenEvent::DISCONNECTED) { - WLOGI("connect screen"); + ProcessScreenDisconnected(rsScreenId); } else { WLOGE("unknow message:%{public}ud", static_cast(screenEvent)); } } +void AbstractScreenController::ProcessScreenDisconnected(ScreenId rsScreenId) +{ + WLOGI("disconnect screen, screenId=%{public}" PRIu64"", rsScreenId); + ScreenId dmsScreenId = INVALID_SCREEN_ID; + auto iter = rs2DmsScreenIdMap_.find(rsScreenId); + if (iter == rs2DmsScreenIdMap_.end()) { + WLOGE("disconnect screen, screenId=%{public}" PRIu64" is not in rs2DmsScreenIdMap_", rsScreenId); + return; + } + dmsScreenId = iter->second; + auto dmsScreenMapIter = dmsScreenMap_.find(dmsScreenId); + if (dmsScreenMapIter != dmsScreenMap_.end()) { + sptr screenGroup = RemoveFromGroupLocked(dmsScreenMapIter->second); + if (screenGroup != nullptr && abstractScreenCallback_ != nullptr) { + abstractScreenCallback_->onDisconnected_(dmsScreenMapIter->second); + } + dmsScreenMap_.erase(dmsScreenMapIter); + auto firstIter = dmsScreenMap_.begin(); + if (firstIter == dmsScreenMap_.end()) { + primaryDmsScreenId_ = SCREEN_ID_INVALID; + } else { + primaryDmsScreenId_ = firstIter->second->dmsId_; + } + } + rs2DmsScreenIdMap_.erase(iter); + dms2RsScreenIdMap_.erase(dmsScreenId); +} + bool AbstractScreenController::FillAbstractScreen(sptr& absScreen, ScreenId rsScreenId) { if (rsInterface_ == nullptr) { @@ -165,41 +193,89 @@ bool AbstractScreenController::FillAbstractScreen(sptr& absScree sptr AbstractScreenController::AddToGroupLocked(sptr newScreen) { - if (primaryDmsScreenId_ == SCREEN_ID_INVALID) { - WLOGI("connect the first screen"); + if (dmsScreenGroupMap_.empty()) { + WLOGE("connect the first screen"); return AddAsFirstScreenLocked(newScreen); - } else { - AddAsSuccedentScreenLocked(newScreen); + } + return AddAsSuccedentScreenLocked(newScreen); +} + +sptr AbstractScreenController::RemoveFromGroupLocked(sptr newScreen) +{ + WLOGI("RemoveFromGroupLocked."); + auto groupDmsId = newScreen->groupDmsId_; + auto iter = dmsScreenGroupMap_.find(groupDmsId); + if (iter == dmsScreenGroupMap_.end()) { + WLOGE("RemoveFromGroupLocked. groupDmsId:%{public}" PRIu64"is not in dmsScreenGroupMap_.", groupDmsId); + return nullptr; + } + sptr screenGroup = iter->second; + bool res = screenGroup->RemoveChild(newScreen); + if (!res) { + WLOGE("RemoveFromGroupLocked. remove screen:%{public}" PRIu64" failed from screenGroup:%{public}" PRIu64".", + newScreen->dmsId_, groupDmsId); return nullptr; } + if (screenGroup->GetChildCount() == 0) { + // Group removed, need to do something. + dmsScreenGroupMap_.erase(screenGroup->dmsId_); + dmsScreenMap_.erase(screenGroup->dmsId_); + } + return screenGroup; } sptr AbstractScreenController::AddAsFirstScreenLocked(sptr newScreen) { ScreenId dmsGroupScreenId = dmsScreenCount_.load(); - sptr sreenGroup = new AbstractScreenGroup(dmsGroupScreenId, SCREEN_ID_INVALID); + sptr screenGroup = + new AbstractScreenGroup(dmsGroupScreenId, SCREEN_ID_INVALID, ScreenCombination::SCREEN_ALONE); Point point; - if (!sreenGroup->AddChild(ScreenCombination::SCREEN_ALONE, newScreen, point)) { + if (!screenGroup->AddChild(newScreen, point)) { WLOGE("fail to add screen to group. screen=%{public}" PRIu64"", newScreen->dmsId_); return nullptr; } dmsScreenCount_++; newScreen->groupDmsId_ = dmsGroupScreenId; + primaryDmsScreenId_ = newScreen->dmsId_; auto iter = dmsScreenGroupMap_.find(dmsGroupScreenId); if (iter != dmsScreenGroupMap_.end()) { WLOGE("group screen existed. id=%{public}" PRIu64"", dmsGroupScreenId); dmsScreenGroupMap_.erase(iter); } - dmsScreenGroupMap_.insert(std::make_pair(dmsGroupScreenId, sreenGroup)); - dmsScreenMap_.insert(std::make_pair(dmsGroupScreenId, sreenGroup)); + dmsScreenGroupMap_.insert(std::make_pair(dmsGroupScreenId, screenGroup)); + dmsScreenMap_.insert(std::make_pair(dmsGroupScreenId, screenGroup)); WLOGI("connect new group screen. id=%{public}" PRIu64"/%{public}" PRIu64", combination:%{public}u", newScreen->dmsId_, dmsGroupScreenId, newScreen->type_); - return sreenGroup; + return screenGroup; } -void AbstractScreenController::AddAsSuccedentScreenLocked(sptr newScreen) +sptr AbstractScreenController::AddAsSuccedentScreenLocked(sptr newScreen) { + auto screenIter = dmsScreenMap_.find(newScreen->dmsId_); + if (screenIter != dmsScreenMap_.end()) { + WLOGE("AddAsSuccedentScreenLocked. screen:%{public}" PRIu64" is already in dmsScreenMap_.", + newScreen->dmsId_); + return nullptr; + } // TODO: Mirror to main screen + auto iter = dmsScreenMap_.find(primaryDmsScreenId_); + if (iter == dmsScreenMap_.end()) { + WLOGE("AddAsSuccedentScreenLocked. primaryDmsScreenId_:%{public}" PRIu64" is not in dmsScreenMap_.", + primaryDmsScreenId_); + return nullptr; + } + auto screen = iter->second; + auto screenGroupIter = dmsScreenGroupMap_.find(screen->groupDmsId_); + if (screenGroupIter == dmsScreenGroupMap_.end()) { + WLOGE("AddAsSuccedentScreenLocked. groupDmsId:%{public}" PRIu64" is not in dmsScreenGroupMap_.", + screen->groupDmsId_); + return nullptr; + } + auto screenGroup = screenGroupIter->second; + Point point; + screenGroup->AddChild(newScreen, point); + newScreen->groupDmsId_ = screenGroup->dmsId_; + return screenGroup; } ScreenId AbstractScreenController::CreateVirtualScreen(VirtualScreenOption option)