diff --git a/dm/src/screen_manager.cpp b/dm/src/screen_manager.cpp index 7118fa882d89c9a098500ec2fd01b6dc52884c73..013b6dcb04806b2d983c20519cb76b5822776041 100644 --- a/dm/src/screen_manager.cpp +++ b/dm/src/screen_manager.cpp @@ -46,6 +46,8 @@ public: DMError UnregisterScreenGroupListener(sptr listener); DMError RegisterVirtualScreenGroupListener(sptr listener); DMError UnregisterVirtualScreenGroupListener(sptr listener); + DMError RegisterDisplayManagerAgent(); + DMError UnregisterDisplayManagerAgent(); void OnRemoteDied(); private: @@ -54,8 +56,7 @@ private: void NotifyScreenChange(const sptr& screenInfo); void NotifyScreenChange(const std::vector>& screenInfos); bool UpdateScreenInfoLocked(sptr); - DMError RegisterDisplayManagerAgent(); - DMError UnregisterDisplayManagerAgent(); + bool isAllListenersRemoved() const; class ScreenManagerListener; diff --git a/test/demo/BUILD.gn b/test/demo/BUILD.gn index 1133a6630159dc49065cbbc074e1235a5692e5b6..98ad67b7a8fea456a8820f74e7dd78e8aff56edd 100644 --- a/test/demo/BUILD.gn +++ b/test/demo/BUILD.gn @@ -137,3 +137,30 @@ ohos_executable("demo_water_mark_listener") { part_name = "window_manager" subsystem_name = "window" } + +ohos_executable("demo_session_manager") { + sources = [ "demo_session_manager.cpp" ] + + include_dirs = [ + "${window_base_path}/interfaces/innerkits/wm", + "${window_base_path}/interfaces/innerkits/dm", + "${window_base_path}/test/common/utils/include", + "${window_base_path}/window_scene/session_manager/include", + "${window_base_path}/window_scene/session_manager_service/include", + "${window_base_path}/wm/include", + ] + + deps = [ + "${graphic_base_path}/graphic_2d/rosen/modules/render_service_base:librender_service_base", + "${window_base_path}/wm:libwm", + "${window_base_path}/dm:libdm", + "${window_base_path}/window_scene/session_manager:session_manager", + ] + + external_deps = [ "c_utils:utils", + "ipc:ipc_core", + ] + + part_name = "window_manager" + subsystem_name = "window" +} diff --git a/test/demo/demo_session_manager.cpp b/test/demo/demo_session_manager.cpp index 599c7cae6a6b226e110551f87b89ba63985d01ce..a455e5e66dcd5df620eabf3f48275686695f7349 100644 --- a/test/demo/demo_session_manager.cpp +++ b/test/demo/demo_session_manager.cpp @@ -18,9 +18,15 @@ #include #include #include +#include "zidl/screen_session_manager_proxy.h" +#include "iconsumer_surface.h" +#include "display_manager.h" +#include "screen_manager.h" +#include using namespace OHOS; using namespace OHOS::Rosen; +using namespace std; int main(int argc, char *argv[]) { @@ -37,9 +43,92 @@ int main(int argc, char *argv[]) if (!proxy) { std::cout << "proxy is nullptr." << std::endl; + } + + std::cout << " ---------------------- " << std::endl; + + DisplayManager& dm = DisplayManager::GetInstance(); + ScreenManager& sm = ScreenManager::GetInstance(); + + auto display = dm.GetDefaultDisplay(); + if (display) { + std::cout << "Name: " << display->GetName() << std::endl; + std::cout << "Id: " << display->GetId() << std::endl; + std::cout << "screenId: " << display->GetScreenId() << std::endl; + std::cout << "Width: " << display->GetWidth() << std::endl; + std::cout << "Height: " << display->GetHeight() << std::endl; + } + + cout << endl; + VirtualScreenOption option; + option.name_ = "myScreenId"; + option.width_ = 720; + option.height_ = 1280; + option.density_ = 1.5f; + option.surface_ = nullptr; + option.flags_ = true; + option.isForShot_ = true; + + ScreenId screenId = sm.CreateVirtualScreen(option); + cout << "ScreenId: " << (int)screenId << endl; + + sptr bufferProducer = nullptr; + auto surface = IConsumerSurface::Create(); + if (surface == nullptr) { + cout << "CreateSurfaceAsConsumer fail" << endl; + } else { + bufferProducer = surface->GetProducer(); + } + + DMError ret; + cout << endl; + ret = sm.SetVirtualScreenSurface(screenId, surface); + if (ret == DMError::DM_OK) { + cout << "SetVirtualScreenSurface succeed!" << endl; + } else { + cout << "SetVirtualScreenSurface failed!" << endl; + } + + cout << endl; + ScreenId screenGroupId; + std::vector mirrorIds; + mirrorIds.push_back(screenId); + ret = sm.MakeMirror(1, mirrorIds, screenGroupId); + if (ret == DMError::DM_OK) { + cout << "MakeMirror succeed!" << endl; + } else { + cout << "MakeMirror failed!" << endl; + } + + auto pixelmap = dm.GetScreenshot(0); + cout <<"0: "; + if (pixelmap == nullptr) { + cout << "pixelmap == nullptr!" << endl; + } else { + cout << "ok!" << endl; + } + + + sleep(2); + + cout << endl; + sptr screenGroup = sm.GetScreenGroup(screenGroupId); + if (screenGroup == nullptr) { + cout << "GetScreenGroupInfoById screenGroup is nullptr!" << endl; + } else { + cout << "GetScreenGroupInfoById screenGroup ok!" << endl; + } + std::vector ids = screenGroup->GetChildIds(); + // void + sm.RemoveVirtualScreenFromGroup(ids); + + + cout << endl; + ret = sm.DestroyVirtualScreen(screenId); + if (ret == DMError::DM_OK) { + cout << "DestroyVirtualScreen succeed!" << endl; } else { - int ret = proxy->GetValueById(1); - std::cout << "ret value: " << ret << std::endl; + cout << "DestroyVirtualScreen failed!" << endl; } return 0; diff --git a/utils/include/screen_group_info.h b/utils/include/screen_group_info.h index b0aa0c55aedf1dbea8bfcc98e7ec93898ad9970d..ca7a0e32ee4836ed2a28d143b99e820f8050939f 100644 --- a/utils/include/screen_group_info.h +++ b/utils/include/screen_group_info.h @@ -24,6 +24,7 @@ namespace OHOS::Rosen { class ScreenGroupInfo : public ScreenInfo { friend class AbstractScreenGroup; +friend class ScreenSessionGroup; public: ScreenGroupInfo() = default; ~ScreenGroupInfo() = default; diff --git a/utils/include/screen_info.h b/utils/include/screen_info.h index 53c6a4acee89eb7d66bcf3549b0bdc816e60832d..6d2d1f5a20fdac70dd10bf3728d9110f1f11ef66 100644 --- a/utils/include/screen_info.h +++ b/utils/include/screen_info.h @@ -29,6 +29,7 @@ enum class ScreenType : uint32_t { }; class ScreenInfo : public Parcelable { friend class AbstractScreen; +friend class ScreenSession; public: ScreenInfo() = default; ~ScreenInfo() = default; diff --git a/window_scene/session/BUILD.gn b/window_scene/session/BUILD.gn index eb73e5f08f457fe620549bc49e1d2cfd9131b2f8..2f3a9ed293b8b61af221dbb2fcbe13f9864fa7fe 100644 --- a/window_scene/session/BUILD.gn +++ b/window_scene/session/BUILD.gn @@ -25,6 +25,9 @@ config("session_public_config") { # for WMError Code "${window_base_path}/interfaces/innerkits/wm", + + "${graphic_base_path}/graphic_2d/rosen/modules/render_service_client/core", + "${window_base_path}/window_scene/session_manager/include", ] } diff --git a/window_scene/session/screen/include/screen_session.h b/window_scene/session/screen/include/screen_session.h index 75282bcb3b8fc67c69624f31a78b2ae52b7eeefc..0920d7055ba3106a4f511bd88fe79f7a6a274d0e 100644 --- a/window_scene/session/screen/include/screen_session.h +++ b/window_scene/session/screen/include/screen_session.h @@ -25,6 +25,10 @@ #include "screen_property.h" #include "dm_common.h" #include "display_info.h" +#include "screen.h" +#include "screen_info.h" +#include "screen_group.h" +#include "screen_group_info.h" namespace OHOS::Rosen { class IScreenChangeListener : public RefBase { @@ -46,6 +50,7 @@ enum class ScreenState : int32_t { class ScreenSession : public RefBase { public: explicit ScreenSession(ScreenId screenId, const ScreenProperty& property); + ScreenSession(const std::string& name, ScreenId smsId, ScreenId rsId); ~ScreenSession() = default; void RegisterScreenChangeListener(IScreenChangeListener* screenChangeListener); @@ -57,16 +62,67 @@ public: ScreenProperty GetScreenProperty() const; std::shared_ptr GetDisplayNode() const; + sptr GetActiveScreenMode() const; + Rotation CalcRotation(Orientation orientation) const; + sptr ConvertToScreenInfo() const; + void FillScreenInfo(sptr info) const; + bool SetOrientation(Orientation orientation); + void InitRSDisplayNode(RSDisplayNodeConfig& config, Point& startPoint); + + std::string name_; + ScreenId screenId_; + ScreenId rsId_; + ScreenType type_ { ScreenType::REAL }; + float virtualPixelRatio_ = { 1.0 }; + Orientation orientation_ { Orientation::UNSPECIFIED }; + + int32_t activeIdx_ { 0 }; + std::vector> modes_ = {}; + Orientation screenRequestedOrientation_ { Orientation::UNSPECIFIED }; + Rotation rotation_ { Rotation::ROTATION_0 }; + + bool isScreenGroup_ { false }; + ScreenId groupSmsId_ { SCREEN_ID_INVALID }; + ScreenId lastGroupSmsId_ { SCREEN_ID_INVALID }; + std::shared_ptr displayNode_; + void Connect(); void Disconnect(); private: - ScreenId screenId_; ScreenProperty property_; - std::shared_ptr displayNode_; + ScreenState screenState_ { ScreenState::INIT }; std::vector screenChangeListenerList_; }; + +class ScreenSessionGroup : public ScreenSession { +public: + ScreenSessionGroup(ScreenId smsId, ScreenId rsId, std::string name, ScreenCombination combination); + ScreenSessionGroup() = delete; + WM_DISALLOW_COPY_AND_MOVE(ScreenSessionGroup); + ~ScreenSessionGroup(); + + bool AddChild(sptr& smsScreen, Point& startPoint); + bool AddChildren(std::vector>& smsScreens, std::vector& startPoints); + bool RemoveChild(sptr& smsScreen); + bool HasChild(ScreenId childScreen) const; + std::vector> GetChildren() const; + std::vector GetChildrenPosition() const; + Point GetChildPosition(ScreenId screenId) const; + size_t GetChildCount() const; + sptr ConvertToScreenGroupInfo() const; + ScreenCombination GetScreenCombination() const; + + ScreenCombination combination_ { ScreenCombination::SCREEN_ALONE }; + ScreenId mirrorScreenId_ { SCREEN_ID_INVALID }; + +private: + bool GetRSDisplayNodeConfig(sptr& dmsScreen, struct RSDisplayNodeConfig& config); + + std::map, Point>> screenSessionMap_; +}; + } // namespace OHOS::Rosen #endif // OHOS_ROSEN_WINDOW_SCENE_SCREEN_SESSION_H diff --git a/window_scene/session/screen/src/screen_session.cpp b/window_scene/session/screen/src/screen_session.cpp index 08d4eae4c5c782b9b4c8e3c0870e20e8141a145e..552d47d82e04c37c554cdd309ccfc3b69e7b09d6 100644 --- a/window_scene/session/screen/src/screen_session.cpp +++ b/window_scene/session/screen/src/screen_session.cpp @@ -16,6 +16,7 @@ #include "session/screen/include/screen_session.h" #include "window_manager_hilog.h" +#include namespace OHOS::Rosen { namespace { @@ -29,6 +30,14 @@ ScreenSession::ScreenSession(ScreenId screenId, const ScreenProperty& property) displayNode_ = Rosen::RSDisplayNode::Create(config); } +ScreenSession::ScreenSession(const std::string& name, ScreenId smsId, ScreenId rsId) + : name_(name), screenId_(smsId), rsId_(rsId) +{ + (void)rsId_; + Rosen::RSDisplayNodeConfig config = { .screenId = screenId_ }; + displayNode_ = Rosen::RSDisplayNode::Create(config); +} + void ScreenSession::RegisterScreenChangeListener(IScreenChangeListener* screenChangeListener) { if (screenChangeListener == nullptr) { @@ -105,4 +114,319 @@ void ScreenSession::Disconnect() listener->OnDisconnect(); } } + +sptr ScreenSession::GetActiveScreenMode() const +{ + if (activeIdx_ < 0 || activeIdx_ >= static_cast(modes_.size())) { + WLOGE("SCB: ScreenSession::GetActiveScreenMode active mode index is wrong: %{public}d", activeIdx_); + return nullptr; + } + return modes_[activeIdx_]; +} + +Rotation ScreenSession::CalcRotation(Orientation orientation) const +{ + sptr info = GetActiveScreenMode(); + if (info == nullptr) { + return Rotation::ROTATION_0; + } + // vertical: phone(Plugin screen); horizontal: pad & external screen + bool isVerticalScreen = info->width_ < info->height_; + switch (orientation) { + case Orientation::UNSPECIFIED: { + return Rotation::ROTATION_0; + } + case Orientation::VERTICAL: { + return isVerticalScreen ? Rotation::ROTATION_0 : Rotation::ROTATION_90; + } + case Orientation::HORIZONTAL: { + return isVerticalScreen ? Rotation::ROTATION_90 : Rotation::ROTATION_0; + } + case Orientation::REVERSE_VERTICAL: { + return isVerticalScreen ? Rotation::ROTATION_180 : Rotation::ROTATION_270; + } + case Orientation::REVERSE_HORIZONTAL: { + return isVerticalScreen ? Rotation::ROTATION_270 : Rotation::ROTATION_180; + } + default: { + WLOGE("unknown orientation %{public}u", orientation); + return Rotation::ROTATION_0; + } + } +} + +sptr ScreenSession::ConvertToScreenInfo() const +{ + sptr info = new(std::nothrow) ScreenInfo(); + if (info == nullptr) { + return nullptr; + } + FillScreenInfo(info); + return info; +} + +void ScreenSession::FillScreenInfo(sptr info) const +{ + if (info == nullptr) { + WLOGE("FillScreenInfo failed! info is nullptr"); + return; + } + info->id_ = screenId_; + info->name_ = name_; + uint32_t width = 0; + uint32_t height = 0; + sptr ScreenSessionModes = GetActiveScreenMode(); + if (ScreenSessionModes != nullptr) { + height = ScreenSessionModes->height_; + width = ScreenSessionModes->width_; + } + float virtualPixelRatio = virtualPixelRatio_; + // "< 1e-6" means virtualPixelRatio is 0. + if (fabsf(virtualPixelRatio) < 1e-6) { + virtualPixelRatio = 1.0f; + } + //ScreenSourceMode sourceMode = GetSourceMode(); + info->virtualPixelRatio_ = virtualPixelRatio; + info->virtualHeight_ = height / virtualPixelRatio; + info->virtualWidth_ = width / virtualPixelRatio; + info->lastParent_ = lastGroupSmsId_; + info->parent_ = groupSmsId_; + info->isScreenGroup_ = isScreenGroup_; + // info->rotation_ = rotation_; + // info->orientation_ = orientation_; + // info->sourceMode_ = sourceMode; + info->type_ = type_; + info->modeId_ = activeIdx_; + info->modes_ = modes_; +} + +bool ScreenSession::SetOrientation(Orientation orientation) +{ + orientation_ = orientation; + return true; +} + +void ScreenSession::InitRSDisplayNode(RSDisplayNodeConfig& config, Point& startPoint) +{ + if (displayNode_ != nullptr) { + displayNode_->SetDisplayNodeMirrorConfig(config); + } else { + std::shared_ptr rsDisplayNode = RSDisplayNode::Create(config); + if (rsDisplayNode == nullptr) { + WLOGE("fail to add child. create rsDisplayNode fail!"); + return; + } + displayNode_ = rsDisplayNode; + } + //rSDisplayNodeConfig_ = config; + WLOGFI("SetDisplayOffset: posX:%{public}d, posY:%{public}d", startPoint.posX_, startPoint.posY_); + displayNode_->SetDisplayOffset(startPoint.posX_, startPoint.posY_); + uint32_t width = 0; + uint32_t height = 0; + sptr abstractScreenModes = GetActiveScreenMode(); + if (abstractScreenModes != nullptr) { + height = abstractScreenModes->height_; + width = abstractScreenModes->width_; + } + RSScreenType screenType; + auto ret = RSInterfaces::GetInstance().GetScreenType(rsId_, screenType); + if (ret == StatusCode::SUCCESS && screenType == RSScreenType::VIRTUAL_TYPE_SCREEN) { + displayNode_->SetSecurityDisplay(true); + WLOGFI("virtualScreen SetSecurityDisplay success"); + } + // If setDisplayOffset is not valid for SetFrame/SetBounds + displayNode_->SetFrame(0, 0, width, height); + displayNode_->SetBounds(0, 0, width, height); + auto transactionProxy = RSTransactionProxy::GetInstance(); + if (transactionProxy != nullptr) { + transactionProxy->FlushImplicitTransaction(); + } +} + +ScreenSessionGroup::ScreenSessionGroup(ScreenId dmsId, ScreenId rsId, + std::string name, ScreenCombination combination) : ScreenSession(name, dmsId, rsId), + combination_(combination) +{ + type_ = ScreenType::UNDEFINED; + isScreenGroup_ = true; +} + +ScreenSessionGroup::~ScreenSessionGroup() +{ + displayNode_ = nullptr; + screenSessionMap_.clear(); +} + +bool ScreenSessionGroup::GetRSDisplayNodeConfig(sptr& dmsScreen, struct RSDisplayNodeConfig& config) +{ + if (dmsScreen == nullptr) { + WLOGE("dmsScreen is nullptr."); + return false; + } + config = { dmsScreen->rsId_ }; + switch (combination_) { + case ScreenCombination::SCREEN_ALONE: + [[fallthrough]]; + case ScreenCombination::SCREEN_EXPAND: + break; + case ScreenCombination::SCREEN_MIRROR: { + if (GetChildCount() == 0 || mirrorScreenId_ == dmsScreen->screenId_) { + WLOGI("AddChild, SCREEN_MIRROR, config is not mirror"); + break; + } + // if (screenController_ == nullptr) { + // return false; + // } + std::shared_ptr displayNode = nullptr; + if (mirrorScreenId_ == SCREEN_ID_INVALID || !HasChild(mirrorScreenId_)) { + WLOGI("AddChild, mirrorScreenId_ is invalid, use default screen"); + //mirrorScreenId_ = screenController_->GetDefaultAbstractScreenId(); + auto mirrorRsScreenId = RSInterfaces::GetInstance().GetDefaultScreenId(); + for (auto iter = screenSessionMap_.begin(); iter != screenSessionMap_.end(); iter++) { + if (iter->second.first->rsId_ == mirrorRsScreenId) { + mirrorScreenId_ = iter->second.first->screenId_; + displayNode = iter->second.first->displayNode_; + } + } + } + + // Todo displayNode is nullptr + //std::shared_ptr displayNode = screenController_->GetRSDisplayNodeByScreenId(mirrorScreenId_); + + if (displayNode == nullptr) { + WLOGFE("AddChild fail, displayNode is nullptr, cannot get DisplayNode"); + break; + } + NodeId nodeId = displayNode->GetId(); + WLOGI("AddChild, mirrorScreenId_:%{public}" PRIu64", rsId_:%{public}" PRIu64", nodeId:%{public}" PRIu64"", + mirrorScreenId_, dmsScreen->rsId_, nodeId); + config = {dmsScreen->rsId_, true, nodeId}; + break; + } + default: + WLOGE("fail to add child. invalid group combination:%{public}u", combination_); + return false; + } + return true; +} + +bool ScreenSessionGroup::AddChild(sptr& smsScreen, Point& startPoint) +{ + if (smsScreen == nullptr) { + WLOGE("AddChild, smsScreen is nullptr."); + return false; + } + ScreenId screenId = smsScreen->screenId_; + auto iter = screenSessionMap_.find(screenId); + if (iter != screenSessionMap_.end()) { + WLOGE("AddChild, screenSessionMap_ has smsScreen:%{public}" PRIu64"", screenId); + return false; + } + struct RSDisplayNodeConfig config; + if (!GetRSDisplayNodeConfig(smsScreen, config)) { + return false; + } + smsScreen->InitRSDisplayNode(config, startPoint); + smsScreen->lastGroupSmsId_ = smsScreen->groupSmsId_; + smsScreen->groupSmsId_ = screenId_; + screenSessionMap_.insert(std::make_pair(screenId, std::make_pair(smsScreen, startPoint))); + return true; +} + +bool ScreenSessionGroup::AddChildren(std::vector>& smsScreens, std::vector& startPoints) +{ + size_t size = smsScreens.size(); + if (size != startPoints.size()) { + WLOGE("AddChildren, unequal size."); + return false; + } + bool res = true; + for (size_t i = 0; i < size; i++) { + res = AddChild(smsScreens[i], startPoints[i]) && res; + } + return res; +} + +bool ScreenSessionGroup::RemoveChild(sptr& smsScreen) +{ + if (smsScreen == nullptr) { + WLOGE("RemoveChild, smsScreen is nullptr."); + return false; + } + ScreenId screenId = smsScreen->screenId_; + smsScreen->lastGroupSmsId_ = smsScreen->groupSmsId_; + smsScreen->groupSmsId_ = SCREEN_ID_INVALID; + if (smsScreen->displayNode_ != nullptr) { + smsScreen->displayNode_->SetDisplayOffset(0, 0); + smsScreen->displayNode_->RemoveFromTree(); + auto transactionProxy = RSTransactionProxy::GetInstance(); + if (transactionProxy != nullptr) { + transactionProxy->FlushImplicitTransaction(); + } + smsScreen->displayNode_ = nullptr; + } + return screenSessionMap_.erase(screenId); + return true; +} + +bool ScreenSessionGroup::HasChild(ScreenId childScreen) const +{ + return screenSessionMap_.find(childScreen) != screenSessionMap_.end(); +} + +std::vector> ScreenSessionGroup::GetChildren() const +{ + std::vector> res; + for (auto iter = screenSessionMap_.begin(); iter != screenSessionMap_.end(); iter++) { + res.push_back(iter->second.first); + } + return res; +} + +std::vector ScreenSessionGroup::GetChildrenPosition() const +{ + std::vector res; + for (auto iter = screenSessionMap_.begin(); iter != screenSessionMap_.end(); iter++) { + res.push_back(iter->second.second); + } + return res; +} + +Point ScreenSessionGroup::GetChildPosition(ScreenId screenId) const +{ + Point point; + auto iter = screenSessionMap_.find(screenId); + if (iter != screenSessionMap_.end()) { + point = iter->second.second; + } + return point; +} + +size_t ScreenSessionGroup::GetChildCount() const +{ + return screenSessionMap_.size(); +} + +ScreenCombination ScreenSessionGroup::GetScreenCombination() const +{ + return combination_; +} + +sptr ScreenSessionGroup::ConvertToScreenGroupInfo() const +{ + sptr screenGroupInfo = new(std::nothrow) ScreenGroupInfo(); + if (screenGroupInfo == nullptr) { + return nullptr; + } + FillScreenInfo(screenGroupInfo); + screenGroupInfo->combination_ = combination_; + for (auto iter = screenSessionMap_.begin(); iter != screenSessionMap_.end(); iter++) { + screenGroupInfo->children_.push_back(iter->first); + } + auto positions = GetChildrenPosition(); + screenGroupInfo->position_.insert(screenGroupInfo->position_.end(), positions.begin(), positions.end()); + return screenGroupInfo; +} + + } // namespace OHOS::Rosen diff --git a/window_scene/session_manager/BUILD.gn b/window_scene/session_manager/BUILD.gn index 75b6a1e4f330030f203d56c903271669c2f2a17f..3c0659fc2e15a76ab0ee3f5c47279af0fea9ca61 100644 --- a/window_scene/session_manager/BUILD.gn +++ b/window_scene/session_manager/BUILD.gn @@ -30,6 +30,7 @@ config("session_manager_public_config") { # for screen_session_manager "${window_base_path}/utils/include", + "//utils/system/safwk/native/include", "${window_base_path}/dm/include", "${window_base_path}/interfaces/innerkits/dm", "${window_base_path}/dmserver/include", @@ -88,6 +89,7 @@ ohos_shared_library("screen_session_manager") { "${window_base_path}/utils:libwmutil", "${window_base_path}/window_scene/common:window_scene_common", "${window_base_path}/window_scene/session:screen_session", + "${window_base_path}/utils:libwmutil", ] external_deps = [ @@ -97,6 +99,12 @@ ohos_shared_library("screen_session_manager") { "ipc:ipc_core", ] + if (is_standard_system) { + external_deps += [ "init:libbegetutil" ] + } else { + external_deps += [ "init_lite:libbegetutil" ] + } + innerapi_tags = [ "platformsdk" ] part_name = "window_manager" subsystem_name = "window" @@ -120,6 +128,7 @@ ohos_shared_library("session_manager") { "${window_base_path}/utils:libwmutil", "${window_base_path}/window_scene/common:window_scene_common", "${window_base_path}/window_scene/session:scene_session", + "${window_base_path}/window_scene/session:screen_session", ] external_deps = [ diff --git a/window_scene/session_manager/include/screen_session_manager.h b/window_scene/session_manager/include/screen_session_manager.h index bcfbdad99a374e41bbffc2b9465ac31e8e43f977..11c5b4740c313fd519b4a71d6bb1cb5099ab1774 100644 --- a/window_scene/session_manager/include/screen_session_manager.h +++ b/window_scene/session_manager/include/screen_session_manager.h @@ -21,6 +21,8 @@ #include "zidl/screen_session_manager_stub.h" #include "client_agent_container.h" #include "singleton_delegator.h" +#include "agent_death_recipient.h" +#include "screen.h" namespace OHOS::Rosen { class IScreenConnectionListener : public RefBase { @@ -48,6 +50,7 @@ public: void RegisterScreenConnectionListener(sptr& screenConnectionListener); void UnregisterScreenConnectionListener(sptr& screenConnectionListener); + // void RegisterRSScreenChangeListener(const sptr& listener); virtual DMError RegisterDisplayManagerAgent(const sptr& displayManagerAgent, DisplayManagerAgentType type) override; @@ -55,11 +58,69 @@ public: virtual DMError UnregisterDisplayManagerAgent(const sptr& displayManagerAgent, DisplayManagerAgentType type) override; + virtual ScreenId CreateVirtualScreen(VirtualScreenOption option, const sptr& displayManagerAgent) override; + virtual DMError SetVirtualScreenSurface(ScreenId screenId, sptr surface) override; + virtual DMError DestroyVirtualScreen(ScreenId screenId) override; + virtual DMError MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenIds, + ScreenId& screenGroupId) override; + virtual sptr GetScreenGroupInfoById(ScreenId screenId) override; + virtual void RemoveVirtualScreenFromGroup(std::vector screens) override; + virtual std::shared_ptr GetDisplaySnapshot(DisplayId displayId, DmErrorCode* errorCode) override; + + + const std::shared_ptr& GetRSDisplayNodeByScreenId(ScreenId smsScreenId) const; + std::shared_ptr GetScreenSnapshot(DisplayId displayId); + + sptr GetAbstractScreen(ScreenId smsScreenId) const; + sptr InitVirtualScreen(ScreenId smsScreenId, ScreenId rsId, VirtualScreenOption option); + void ProcessScreenDisconnected(ScreenId rsScreenId); + ScreenId GetDefaultAbstractScreenId(); + sptr InitAndGetScreen(ScreenId rsScreenId); + bool InitAbstractScreenModesInfo(sptr& absScreen); + void ProcessScreenConnected(ScreenId rsScreenId); + std::vector GetAllValidScreenIds(const std::vector& screenIds) const; + + sptr AddToGroupLocked(sptr newScreen); + sptr AddAsFirstScreenLocked(sptr newScreen); + sptr AddAsSuccedentScreenLocked(sptr newScreen); + sptr RemoveFromGroupLocked(sptr screen); + sptr GetAbstractScreenGroup(ScreenId smsScreenId); + + void ChangeScreenGroup(sptr group, const std::vector& screens, + const std::vector& startPoints, bool filterScreen, ScreenCombination combination); + + bool RemoveChildFromGroup(sptr screen, sptr screenGroup); + + void AddScreenToGroup(sptr group, + const std::vector& addScreens, const std::vector& addChildPos, + std::map& removeChildResMap); + + DMError SetMirror(ScreenId screenId, std::vector screens); + + + void NotifyScreenConnected(sptr screenInfo); + void NotifyScreenDisconnected(ScreenId screenId); + void NotifyScreenGroupChanged(const sptr& screenInfo, ScreenGroupChangeEvent event); + void NotifyScreenGroupChanged(const std::vector>& screenInfo, ScreenGroupChangeEvent event); + + + void OnScreenConnect(const sptr screenInfo); + void OnScreenDisconnect(ScreenId screenId); + void OnScreenGroupChange(const std::string& trigger, + const sptr& screenInfo, ScreenGroupChangeEvent groupEvent); + void OnScreenGroupChange(const std::string& trigger, + const std::vector>& screenInfos, ScreenGroupChangeEvent groupEvent); + void OnScreenshot(sptr info); + protected: ScreenSessionManager(); virtual ~ScreenSessionManager() = default; private: + static inline bool IsVertical(Rotation rotation) + { + return (rotation == Rotation::ROTATION_0 || rotation == Rotation::ROTATION_180); + } void Init(); void RegisterScreenChangeListener(); void OnScreenChange(ScreenId screenId, ScreenEvent screenEvent); @@ -67,6 +128,30 @@ private: ScreenId GetDefaultScreenId(); + bool OnRemoteDied(const sptr& agent); + + class ScreenIdManager { + friend class ScreenSessionGroup; + public: + ScreenIdManager() = default; + ~ScreenIdManager() = default; + WM_DISALLOW_COPY_AND_MOVE(ScreenIdManager); + ScreenId CreateAndGetNewScreenId(ScreenId rsScreenId); + bool DeleteScreenId(ScreenId smsScreenId); + //bool HasDmsScreenId(ScreenId dmsScreenId) const; + bool HasRsScreenId(ScreenId smsScreenId) const; + bool ConvertToRsScreenId(ScreenId, ScreenId&) const; + //ScreenId ConvertToRsScreenId(ScreenId) const; + bool ConvertToSmsScreenId(ScreenId, ScreenId&) const; + ScreenId ConvertToSmsScreenId(ScreenId) const; + //uint32_t GetRSScreenNum() const; + private: + std::atomic smsScreenCount_ {0}; + std::map rs2SmsScreenIdMap_; + std::map sms2RsScreenIdMap_; + }; + + RSInterfaces& rsInterface_; std::shared_ptr msgScheduler_ = nullptr; std::map> screenSessionMap_; @@ -74,6 +159,20 @@ private: ScreenId defaultScreenId_ = SCREEN_ID_INVALID; + ScreenIdManager screenIdManager_; + + std::atomic defaultRsScreenId_ {SCREEN_ID_INVALID }; + std::map, std::vector> screenAgentMap_; + std::map> smsScreenGroupMap_; + + Orientation buildInDefaultOrientation_ { Orientation::UNSPECIFIED }; + + bool isExpandCombination_ = false; + sptr deathRecipient_ { nullptr }; + + // sptr rSScreenChangeListener_; + std::shared_ptr controllerHandler_; + std::vector> screenConnectionListenerList_; }; } // namespace OHOS::Rosen diff --git a/window_scene/session_manager/include/zidl/screen_session_manager_proxy.h b/window_scene/session_manager/include/zidl/screen_session_manager_proxy.h index a41686b941e5ec2d7ddd656dbf766ca32f236e3a..9a8d5bf49e8765e038af26d7ce34c87e7fbdd206 100644 --- a/window_scene/session_manager/include/zidl/screen_session_manager_proxy.h +++ b/window_scene/session_manager/include/zidl/screen_session_manager_proxy.h @@ -37,6 +37,23 @@ public: virtual DMError UnregisterDisplayManagerAgent(const sptr& displayManagerAgent, DisplayManagerAgentType type) override; + virtual ScreenId CreateVirtualScreen(VirtualScreenOption option, + const sptr& displayManagerAgent) override; + + virtual DMError DestroyVirtualScreen(ScreenId screenId) override; + + virtual DMError SetVirtualScreenSurface(ScreenId screenId, sptr surface) override; + + virtual DMError MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenIds, + ScreenId& screenGroupId) override; + + virtual sptr GetScreenGroupInfoById(ScreenId screenId) override; + + virtual void RemoveVirtualScreenFromGroup(std::vector screens) override; + + virtual std::shared_ptr GetDisplaySnapshot(DisplayId displayId, DmErrorCode* errorCode) override; + + private: static inline BrokerDelegator delegator_; }; diff --git a/window_scene/session_manager/src/screen_session_manager.cpp b/window_scene/session_manager/src/screen_session_manager.cpp index 03070ee0e5ef4e477c6cac62943efd5b777cc971..320aeaf9126b166c48e87ef342c8016207c86063 100644 --- a/window_scene/session_manager/src/screen_session_manager.cpp +++ b/window_scene/session_manager/src/screen_session_manager.cpp @@ -19,11 +19,15 @@ #include "window_manager_hilog.h" #include "screen_session_manager.h" #include "permission.h" +#include +#include "sys_cap_util.h" +#include "surface_capture_future.h" namespace OHOS::Rosen { namespace { constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, HILOG_DOMAIN_WINDOW, "ScreenSessionManager" }; const std::string SCREEN_SESSION_MANAGER_THREAD = "ScreenSessionManager"; +const std::string CONTROLLER_THREAD_ID = "ScreenSessionManagerThread"; } // namespace ScreenSessionManager& ScreenSessionManager::GetInstance() @@ -70,44 +74,20 @@ void ScreenSessionManager::UnregisterScreenConnectionListener(sptr& displayManagerAgent, DisplayManagerAgentType type) -{ - if (type == DisplayManagerAgentType::SCREEN_EVENT_LISTENER && !Permission::IsSystemCalling() - && !Permission::IsStartByHdcd()) { - WLOGFE("register display manager agent permission denied!"); - return DMError::DM_ERROR_NOT_SYSTEM_APP; - } - if ((displayManagerAgent == nullptr) || (displayManagerAgent->AsObject() == nullptr)) { - WLOGFE("displayManagerAgent invalid"); - return DMError::DM_ERROR_NULLPTR; - } - - return dmAgentContainer_.RegisterAgent(displayManagerAgent, type) ? DMError::DM_OK :DMError::DM_ERROR_NULLPTR; -} - -DMError ScreenSessionManager::UnregisterDisplayManagerAgent( - const sptr& displayManagerAgent, DisplayManagerAgentType type) -{ - if (type == DisplayManagerAgentType::SCREEN_EVENT_LISTENER && !Permission::IsSystemCalling() - && !Permission::IsStartByHdcd()) { - WLOGFE("unregister display manager agent permission denied!"); - return DMError::DM_ERROR_NOT_SYSTEM_APP; - } - if ((displayManagerAgent == nullptr) || (displayManagerAgent->AsObject() == nullptr)) { - WLOGFE("displayManagerAgent invalid"); - return DMError::DM_ERROR_NULLPTR; - } - - return dmAgentContainer_.UnregisterAgent(displayManagerAgent, type) ? DMError::DM_OK :DMError::DM_ERROR_NULLPTR; -} - void ScreenSessionManager::Init() { msgScheduler_ = std::make_shared(SCREEN_SESSION_MANAGER_THREAD); RegisterScreenChangeListener(); + auto runner = AppExecFwk::EventRunner::Create(CONTROLLER_THREAD_ID); + controllerHandler_ = std::make_shared(runner); } +// void ScreenSessionManager::RegisterRSScreenChangeListener(const sptr& listener) +// { +// //std::lock_guard lock(mutex_); +// rSScreenChangeListener_ = listener; +// } + void ScreenSessionManager::RegisterScreenChangeListener() { WLOGFD("Register screen change listener."); @@ -187,6 +167,7 @@ sptr ScreenSessionManager::GetOrCreateScreenSession(ScreenId scre screenSessionMap_[screenId] = session; return session; } + ScreenId ScreenSessionManager::GetDefaultScreenId() { if (defaultScreenId_ == INVALID_SCREEN_ID) { @@ -194,4 +175,966 @@ ScreenId ScreenSessionManager::GetDefaultScreenId() } return defaultScreenId_; } + +ScreenId ScreenSessionManager::CreateVirtualScreen(VirtualScreenOption option, const sptr& displayManagerAgent) +{ + WLOGFI("SCB: ScreenSessionManager::CreateVirtualScreen ENTER"); + ScreenId rsId = rsInterface_.CreateVirtualScreen(option.name_, option.width_, + option.height_, option.surface_, SCREEN_ID_INVALID, option.flags_); + WLOGFI("SCB: ScreenSessionManager::CreateVirtualScreen rsid: %{public}" PRIu64"", rsId); + if (rsId == SCREEN_ID_INVALID) { + WLOGFI("SCB: ScreenSessionManager::CreateVirtualScreen rsid is invalid"); + return SCREEN_ID_INVALID; + } + //std::lock_guard lock(mutex_); + ScreenId smsScreenId = SCREEN_ID_INVALID; + if (!screenIdManager_.ConvertToSmsScreenId(rsId, smsScreenId)) { + WLOGFI("SCB: ScreenSessionManager::CreateVirtualScreen !ConvertToSmsScreenId(rsId, smsScreenId)"); + smsScreenId = screenIdManager_.CreateAndGetNewScreenId(rsId); + auto screenSession = InitVirtualScreen(smsScreenId, rsId, option); + if (screenSession == nullptr) { + WLOGFI("SCB: ScreenSessionManager::CreateVirtualScreen screensession is nullptr"); + screenIdManager_.DeleteScreenId(smsScreenId); + return SCREEN_ID_INVALID; + } + screenSessionMap_.insert(std::make_pair(smsScreenId, screenSession)); + NotifyScreenConnected(screenSession->ConvertToScreenInfo()); + if (deathRecipient_ == nullptr) { + WLOGFI("SCB: ScreenSessionManager::CreateVirtualScreen Create deathRecipient"); + deathRecipient_ = + new AgentDeathRecipient([this](const sptr& agent) { OnRemoteDied(agent); }); + } + auto agIter = screenAgentMap_.find(displayManagerAgent); + if (agIter == screenAgentMap_.end()) { + //displayManagerAgent->AddDeathRecipient(deathRecipient_); + } + screenAgentMap_[displayManagerAgent].emplace_back(smsScreenId); + } else { + WLOGFI("SCB: ScreenSessionManager::CreateVirtualScreen id: %{public}" PRIu64" appears in screenIdManager_. ", rsId); + } + WLOGFI("SCB: ScreenSessionManager::CreateVirtualScreen END"); + return smsScreenId; +} + +DMError ScreenSessionManager::SetVirtualScreenSurface(ScreenId screenId, sptr surface) +{ + WLOGFI("SCB: ScreenSessionManager::SetVirtualScreenSurface ENTER"); + int32_t res = -1; + ScreenId rsScreenId; + if (screenIdManager_.ConvertToRsScreenId(screenId, rsScreenId)) { + sptr pSurface = Surface::CreateSurfaceAsProducer(surface); + res = rsInterface_.SetVirtualScreenSurface(rsScreenId, pSurface); + } + if (res != 0) { + WLOGE("SCB: ScreenSessionManager::SetVirtualScreenSurface failed in RenderService"); + //return DMError::DM_ERROR_RENDER_SERVICE_FAILED; + } + return DMError::DM_OK; +} + +DMError ScreenSessionManager::DestroyVirtualScreen(ScreenId screenId) +{ + WLOGE("SCB: ScreenSessionManager::DestroyVirtualScreen Enter"); + //std::lock_guard lock(mutex_); + ScreenId rsScreenId = SCREEN_ID_INVALID; + screenIdManager_.ConvertToRsScreenId(screenId, rsScreenId); + + // for register agent + 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) { + if (agentIter.first != nullptr && agentIter.second.empty()) { + //agentIter.first->RemoveDeathRecipient(deathRecipient_); + screenAgentMap_.erase(agentIter.first); + } + break; + } + } + + if (rsScreenId != SCREEN_ID_INVALID && GetAbstractScreen(screenId) != nullptr) { + ProcessScreenDisconnected(rsScreenId); + } + screenIdManager_.DeleteScreenId(screenId); + + if (rsScreenId == SCREEN_ID_INVALID) { + WLOGFE("SCB: ScreenSessionManager::DestroyVirtualScreen: No corresponding rsScreenId"); + return DMError::DM_ERROR_INVALID_PARAM; + } + rsInterface_.RemoveVirtualScreen(rsScreenId); + return DMError::DM_OK; +} + +DMError ScreenSessionManager::MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenIds, + ScreenId& screenGroupId) +{ + WLOGFE("SCB:ScreenSessionManager::MakeMirror enter!"); + if (!Permission::IsSystemCalling() && !Permission::IsStartByHdcd()) { + WLOGFE("SCB:ScreenSessionManager::MakeMirror permission denied!"); + //return DMError::DM_ERROR_NOT_SYSTEM_APP; + } + WLOGFI("SCB:ScreenSessionManager::MakeMirror mainScreenId :%{public}" PRIu64"", mainScreenId); + auto allMirrorScreenIds = GetAllValidScreenIds(mirrorScreenIds); + auto iter = std::find(allMirrorScreenIds.begin(), allMirrorScreenIds.end(), mainScreenId); + if (iter != allMirrorScreenIds.end()) { + allMirrorScreenIds.erase(iter); + } + auto mainScreen = GetAbstractScreen(mainScreenId); + + if (mainScreen == nullptr || allMirrorScreenIds.empty()) { + WLOGFI("SCB:ScreenSessionManager::MakeMirror create fail. main screen :%{public}" PRIu64", screens' size:%{public}u", + mainScreenId, static_cast(allMirrorScreenIds.size())); + return DMError::DM_ERROR_INVALID_PARAM; + } + //HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "sms:MakeMirror"); + DMError ret = SetMirror(mainScreenId, allMirrorScreenIds); + if (ret != DMError::DM_OK) { + WLOGFE("SCB:ScreenSessionManager::MakeMirror set mirror failed."); + return ret; + } + if (GetAbstractScreenGroup(mainScreen->groupSmsId_) == nullptr) { + WLOGFE("SCB:ScreenSessionManager::MakeMirror get screen group failed."); + return DMError::DM_ERROR_NULLPTR; + } + screenGroupId = mainScreen->groupSmsId_; + return DMError::DM_OK; +} + +bool ScreenSessionManager::ScreenIdManager::ConvertToRsScreenId(ScreenId smsScreenId, ScreenId& rsScreenId) const +{ + auto iter = sms2RsScreenIdMap_.find(smsScreenId); + if (iter == sms2RsScreenIdMap_.end()) { + return false; + } + rsScreenId = iter->second; + return true; +} + +ScreenId ScreenSessionManager::ScreenIdManager::ConvertToSmsScreenId(ScreenId rsScreenId) const +{ + ScreenId smsScreenId = SCREEN_ID_INVALID; + ConvertToSmsScreenId(rsScreenId, smsScreenId); + return smsScreenId; +} + +bool ScreenSessionManager::ScreenIdManager::ConvertToSmsScreenId(ScreenId rsScreenId, ScreenId& smsScreenId) const +{ + auto iter = rs2SmsScreenIdMap_.find(rsScreenId); + if (iter == rs2SmsScreenIdMap_.end()) { + return false; + } + smsScreenId = iter->second; + return true; +} + +ScreenId ScreenSessionManager::ScreenIdManager::CreateAndGetNewScreenId(ScreenId rsScreenId) +{ + ScreenId smsScreenId = smsScreenCount_++; + WLOGFW("SCB: ScreenSessionManager::CreateAndGetNewScreenId screenId: %{public}" PRIu64"", smsScreenId); + if (sms2RsScreenIdMap_.find(smsScreenId) != sms2RsScreenIdMap_.end()) { + WLOGFW("SCB: ScreenSessionManager::CreateAndGetNewScreenId dmsScreenId: %{public}" PRIu64" exit in dms2RsScreenIdMap_, warning.", smsScreenId); + } + sms2RsScreenIdMap_[smsScreenId] = rsScreenId; + if (rsScreenId == SCREEN_ID_INVALID) { + return smsScreenId; + } + if (rs2SmsScreenIdMap_.find(rsScreenId) != rs2SmsScreenIdMap_.end()) { + WLOGFW("SCB: ScreenSessionManager::CreateAndGetNewScreenId rsScreenId: %{public}" PRIu64" exit in rs2DmsScreenIdMap_, warning.", rsScreenId); + } + rs2SmsScreenIdMap_[rsScreenId] = smsScreenId; + return smsScreenId; +} + +// function name should be changed, use old name temporarily +sptr ScreenSessionManager::GetAbstractScreen(ScreenId smsScreenId) const +{ + //std::lock_guard lock(mutex_); + auto iter = screenSessionMap_.find(smsScreenId); + if (iter == screenSessionMap_.end()) { + WLOGE("SCB: GetAbstractScreen: did not find screen:%{public}" PRIu64"", smsScreenId); + return nullptr; + } + return iter->second; +} + +bool ScreenSessionManager::ScreenIdManager::DeleteScreenId(ScreenId smsScreenId) +{ + auto iter = sms2RsScreenIdMap_.find(smsScreenId); + if (iter == sms2RsScreenIdMap_.end()) { + return false; + } + ScreenId rsScreenId = iter->second; + sms2RsScreenIdMap_.erase(smsScreenId); + rs2SmsScreenIdMap_.erase(rsScreenId); + return true; +} + +bool ScreenSessionManager::ScreenIdManager::HasRsScreenId(ScreenId smsScreenId) const +{ + return rs2SmsScreenIdMap_.find(smsScreenId) != rs2SmsScreenIdMap_.end(); +} + +ScreenId ScreenSessionManager::GetDefaultAbstractScreenId() +{ + //WLOGFI("SCB: ScreenSessionManager::GetDefaultAbstractScreenId ENTER"); + if (defaultRsScreenId_ == SCREEN_ID_INVALID) { + defaultRsScreenId_ = rsInterface_.GetDefaultScreenId(); + } + if (defaultRsScreenId_ == SCREEN_ID_INVALID) { + WLOGFW("SCB: ScreenSessionManager::GetDefaultAbstractScreenId, rsDefaultId is invalid."); + return SCREEN_ID_INVALID; + } + //std::lock_guard lock(mutex_); + ScreenId defaultSmsScreenId; + if (screenIdManager_.ConvertToSmsScreenId(defaultRsScreenId_, defaultSmsScreenId)) { + WLOGFI("SCB: ScreenSessionManager::GetDefaultAbstractScreenId, screen:%{public}" PRIu64"", defaultSmsScreenId); + return defaultSmsScreenId; + } + WLOGFI("SCB: ScreenSessionManager::GetDefaultAbstractScreenId, default screen is null, try to get."); + ProcessScreenConnected(defaultRsScreenId_); + //WLOGFI("SCB: ScreenSessionManager::GetDefaultAbstractScreenId END"); + return screenIdManager_.ConvertToSmsScreenId(defaultRsScreenId_); +} + +sptr ScreenSessionManager::InitVirtualScreen(ScreenId smsScreenId, ScreenId rsId, + VirtualScreenOption option) +{ + //WLOGFI("SCB: ScreenSessionManager::InitVirtualScreen: Enter"); + sptr screenSession = new(std::nothrow) ScreenSession(option.name_, smsScreenId, rsId); + sptr info = new(std::nothrow) SupportedScreenModes(); + if (screenSession == nullptr || info == nullptr) { + WLOGFI("SCB: ScreenSessionManager::InitVirtualScreen: new screenSession or info failed"); + screenIdManager_.DeleteScreenId(smsScreenId); + rsInterface_.RemoveVirtualScreen(rsId); + return nullptr; + } + info->width_ = option.width_; + info->height_ = option.height_; + auto defaultScreen = GetAbstractScreen(GetDefaultAbstractScreenId()); + if (defaultScreen != nullptr && defaultScreen->GetActiveScreenMode() != nullptr) { + info->refreshRate_ = defaultScreen->GetActiveScreenMode()->refreshRate_; + } + screenSession->modes_.emplace_back(info); + screenSession->activeIdx_ = 0; + screenSession->type_ = ScreenType::VIRTUAL; + screenSession->virtualPixelRatio_ = option.density_; + //WLOGFI("SCB: ScreenSessionManager::InitVirtualScreen: END"); + return screenSession; +} + +bool ScreenSessionManager::InitAbstractScreenModesInfo(sptr& screenSession) +{ + //WLOGE("SCB: ScreenSessionManager::InitAbstractScreenModesInfo: ENTER"); + std::vector allModes = rsInterface_.GetScreenSupportedModes(screenSession->rsId_); + if (allModes.size() == 0) { + WLOGE("SCB: ScreenSessionManager::InitAbstractScreenModesInfo: allModes.size() == 0, screenId=%{public}" PRIu64"", screenSession->rsId_); + return false; + } + for (const RSScreenModeInfo& rsScreenModeInfo : allModes) { + sptr info = new(std::nothrow) SupportedScreenModes(); + if (info == nullptr) { + WLOGFE("SCB: ScreenSessionManager::InitAbstractScreenModesInfo:create SupportedScreenModes failed"); + return false; + } + info->width_ = static_cast(rsScreenModeInfo.GetScreenWidth()); + info->height_ = static_cast(rsScreenModeInfo.GetScreenHeight()); + info->refreshRate_ = rsScreenModeInfo.GetScreenRefreshRate(); + screenSession->modes_.push_back(info); + WLOGI("SCB: ScreenSessionManager::InitAbstractScreenModesInfo:fill screen idx:%{public}d w/h:%{public}d/%{public}d", + rsScreenModeInfo.GetScreenModeId(), info->width_, info->height_); + } + int32_t activeModeId = rsInterface_.GetScreenActiveMode(screenSession->rsId_).GetScreenModeId(); + WLOGI("SCB: ScreenSessionManager::InitAbstractScreenModesInfo: fill screen activeModeId:%{public}d", activeModeId); + if (static_cast(activeModeId) >= allModes.size()) { + WLOGE("SCB: ScreenSessionManager::InitAbstractScreenModesInfo: activeModeId exceed, screenId=%{public}" PRIu64", activeModeId:%{public}d/%{public}ud", + screenSession->rsId_, activeModeId, static_cast(allModes.size())); + return false; + } + screenSession->activeIdx_ = activeModeId; + return true; +} + +sptr ScreenSessionManager::InitAndGetScreen(ScreenId rsScreenId) +{ + //WLOGFE("SCB: ScreenSessionManager::InitAndGetScreen: ENTER"); + ScreenId smsScreenId = screenIdManager_.CreateAndGetNewScreenId(rsScreenId); + std::ostringstream buffer; + buffer< screenSession = + new(std::nothrow) ScreenSession(name, smsScreenId, rsScreenId); + if (screenSession == nullptr) { + WLOGFE("SCB: ScreenSessionManager::InitAndGetScreen: screenSession == nullptr."); + screenIdManager_.DeleteScreenId(smsScreenId); + return nullptr; + } + if (!InitAbstractScreenModesInfo(screenSession)) { + screenIdManager_.DeleteScreenId(smsScreenId); + WLOGFE("SCB: ScreenSessionManager::InitAndGetScreen: InitAndGetScreen failed."); + return nullptr; + } + screenSessionMap_.insert(std::make_pair(smsScreenId, screenSession)); + return screenSession; +} + +void ScreenSessionManager::ProcessScreenConnected(ScreenId rsScreenId) +{ + //WLOGFI("SCB: ScreenSessionManager::ProcessScreenConnected: ENTER"); + //std::lock_guard lock(mutex_); + if (screenIdManager_.HasRsScreenId(rsScreenId)) { + WLOGE("SCB: ScreenSessionManager::ProcessScreenConnected: HasRsScreenId, screenId=%{public}" PRIu64"", rsScreenId); + return; + } + //WLOGFI("SCB: ScreenSessionManager::ProcessScreenConnected: connect new screen"); + auto screenSession = InitAndGetScreen(rsScreenId); + if (screenSession == nullptr) { + WLOGFI("SCB: ScreenSessionManager::ProcessScreenConnected: screenSession == nullptr"); + return; + } + sptr screenGroup = AddToGroupLocked(screenSession); + if (screenGroup == nullptr) { + return; + } + if (rsScreenId == rsInterface_.GetDefaultScreenId() && screenSession->displayNode_ != nullptr) { + WLOGFI("SCB: ScreenSessionManager::ProcessScreenConnected: ENTER IF BRANCH"); + screenSession->screenRequestedOrientation_ = buildInDefaultOrientation_; + Rotation rotationAfter = screenSession->CalcRotation(screenSession->screenRequestedOrientation_); + WLOGFI("SCB: ScreenSessionManager::ProcessScreenConnected set default rotation to %{public}d for buildin screen", rotationAfter); + sptr abstractScreenModes = screenSession->GetActiveScreenMode(); + if (abstractScreenModes != nullptr) { + WLOGFI("SCB: ScreenSessionManager::ProcessScreenConnected: abstractScreenModes != nullptr"); + float w = abstractScreenModes->width_; + float h = abstractScreenModes->height_; + float x = 0; + float y = 0; + if (!IsVertical(rotationAfter)) { + std::swap(w, h); + x = (h - w) / 2; // 2: used to calculate offset to center display node + y = (w - h) / 2; // 2: used to calculate offset to center display node + } + // 90.f is base degree + screenSession->displayNode_->SetRotation(-90.0f * static_cast(rotationAfter)); + screenSession->displayNode_->SetFrame(x, y, w, h); + screenSession->displayNode_->SetBounds(x, y, w, h); + auto transactionProxy = RSTransactionProxy::GetInstance(); + if (transactionProxy != nullptr) { + transactionProxy->FlushImplicitTransaction(); + } + screenSession->rotation_ = rotationAfter; + screenSession->SetOrientation(screenSession->screenRequestedOrientation_); + } + } + NotifyScreenConnected(screenSession->ConvertToScreenInfo()); + NotifyScreenGroupChanged(screenSession->ConvertToScreenInfo(), ScreenGroupChangeEvent::ADD_TO_GROUP); + // if (abstractScreenCallback_ != nullptr) { + // abstractScreenCallback_->onConnect_(screenSession); + // } + // if (screenConnectionListenerList_.size() != 0) { + // WLOGFI("SCB: ScreenSessionManager::ProcessScreenConnected: screenConnectionListenerList_.size()"); + // OnScreenChange(screenSession, ScreenEvent::CONNECTED); + // } + //OnScreenChange(screenSession, ScreenEvent::CONNECTED); + // if (rSScreenChangeListener_ != nullptr) { + // rSScreenChangeListener_->onConnected_(); + // } + WLOGFI("SCB: ScreenSessionManager::ProcessScreenConnected: END"); +} + +void ScreenSessionManager::ProcessScreenDisconnected(ScreenId rsScreenId) +{ + //WLOGFI("SCB: ScreenSessionManager::ProcessScreenDisconnected, screenId=%{public}" PRIu64"", rsScreenId); + ScreenId smsScreenId; + //std::lock_guard lock(mutex_); + if (!screenIdManager_.ConvertToSmsScreenId(rsScreenId, smsScreenId)) { + WLOGFE("SCB: ScreenSessionManager::ProcessScreenDisconnected, screenId=%{public}" PRIu64" not in rs2DmsScreenIdMap_", rsScreenId); + return; + } + auto smsScreenMapIter = screenSessionMap_.find(smsScreenId); + sptr screenGroup; + if (smsScreenMapIter != screenSessionMap_.end()) { + auto screen = smsScreenMapIter->second; + // if (abstractScreenCallback_ != nullptr && CheckScreenInScreenGroup(screen)) { + // abstractScreenCallback_->onDisconnect_(screen); + // } + //OnScreenChange(smsScreenId, ScreenEvent::DISCONNECTED); + screenGroup = RemoveFromGroupLocked(screen); + if (screenGroup != nullptr) { + NotifyScreenGroupChanged(screen->ConvertToScreenInfo(), ScreenGroupChangeEvent::REMOVE_FROM_GROUP); + } + screenSessionMap_.erase(smsScreenMapIter); + WLOGFI("SCB: ScreenSessionManager::ProcessScreenDisconnected screenSessionMap_.erase %{public}" PRIu64 " ", smsScreenId); + NotifyScreenDisconnected(smsScreenId); + // if (rSScreenChangeListener_ != nullptr) { + // rSScreenChangeListener_->onDisconnected_(); + // } + if (screenGroup != nullptr && screenGroup->combination_ == ScreenCombination::SCREEN_MIRROR && + screen->screenId_ == screenGroup->mirrorScreenId_ && screenGroup->GetChildCount() != 0) { + auto defaultScreenId = GetDefaultAbstractScreenId(); + std::vector screens; + for (auto& screenItem : screenGroup->GetChildren()) { + if (screenItem->screenId_ != defaultScreenId) { + screens.emplace_back(screenItem->screenId_); + } + } + SetMirror(defaultScreenId, screens); + } + } + screenIdManager_.DeleteScreenId(smsScreenId); +} + +sptr ScreenSessionManager::AddToGroupLocked(sptr newScreen) +{ + sptr res; + if (smsScreenGroupMap_.empty()) { + WLOGI("connect the first screen"); + res = AddAsFirstScreenLocked(newScreen); + } else { + res = AddAsSuccedentScreenLocked(newScreen); + } + return res; +} + +sptr ScreenSessionManager::AddAsFirstScreenLocked(sptr newScreen) +{ + ScreenId smsGroupScreenId = screenIdManager_.CreateAndGetNewScreenId(SCREEN_ID_INVALID); + std::ostringstream buffer; + buffer<<"ScreenGroup_"< screenGroup; + if (isExpandCombination_) { + screenGroup = new(std::nothrow) ScreenSessionGroup(smsGroupScreenId, + SCREEN_ID_INVALID, name, ScreenCombination::SCREEN_EXPAND); + } else { + screenGroup = new(std::nothrow) ScreenSessionGroup(smsGroupScreenId, + SCREEN_ID_INVALID, name, ScreenCombination::SCREEN_MIRROR); + } + + if (screenGroup == nullptr) { + WLOGE("new ScreenSessionGroup failed"); + screenIdManager_.DeleteScreenId(smsGroupScreenId); + return nullptr; + } + Point point; + if (!screenGroup->AddChild(newScreen, point)) { + WLOGE("fail to add screen to group. screen=%{public}" PRIu64"", newScreen->screenId_); + screenIdManager_.DeleteScreenId(smsGroupScreenId); + return nullptr; + } + auto iter = smsScreenGroupMap_.find(smsGroupScreenId); + if (iter != smsScreenGroupMap_.end()) { + WLOGE("group screen existed. id=%{public}" PRIu64"", smsGroupScreenId); + smsScreenGroupMap_.erase(iter); + } + smsScreenGroupMap_.insert(std::make_pair(smsGroupScreenId, screenGroup)); + screenSessionMap_.insert(std::make_pair(smsGroupScreenId, screenGroup)); + screenGroup->mirrorScreenId_ = newScreen->screenId_; + WLOGI("connect new group screen, screenId: %{public}" PRIu64", screenGroupId: %{public}" PRIu64", " + "combination:%{public}u", newScreen->screenId_, smsGroupScreenId, newScreen->type_); + return screenGroup; +} + +sptr ScreenSessionManager::AddAsSuccedentScreenLocked(sptr newScreen) +{ + ScreenId defaultScreenId = GetDefaultAbstractScreenId(); + auto iter = screenSessionMap_.find(defaultScreenId); + if (iter == screenSessionMap_.end()) { + WLOGE("AddAsSuccedentScreenLocked. defaultScreenId:%{public}" PRIu64" is not in screenSessionMap_.", + defaultScreenId); + return nullptr; + } + auto screen = iter->second; + auto screenGroupIter = smsScreenGroupMap_.find(screen->groupSmsId_); + if (screenGroupIter == smsScreenGroupMap_.end()) { + WLOGE("AddAsSuccedentScreenLocked. groupSmsId:%{public}" PRIu64" is not in smsScreenGroupMap_.", + screen->groupSmsId_); + return nullptr; + } + auto screenGroup = screenGroupIter->second; + Point point; + if (screenGroup->combination_ == ScreenCombination::SCREEN_EXPAND) { + point = {screen->GetActiveScreenMode()->width_, 0}; + } + screenGroup->AddChild(newScreen, point); + return screenGroup; +} + +sptr ScreenSessionManager::RemoveFromGroupLocked(sptr screen) +{ + WLOGI("RemoveFromGroupLocked."); + auto groupSmsId = screen->groupSmsId_; + auto iter = smsScreenGroupMap_.find(groupSmsId); + if (iter == smsScreenGroupMap_.end()) { + WLOGE("RemoveFromGroupLocked. groupSmsId:%{public}" PRIu64"is not in smsScreenGroupMap_.", groupSmsId); + return nullptr; + } + sptr screenGroup = iter->second; + if (!RemoveChildFromGroup(screen, screenGroup)) { + return nullptr; + } + return screenGroup; +} + +bool ScreenSessionManager::RemoveChildFromGroup(sptr screen, sptr screenGroup) +{ + bool res = screenGroup->RemoveChild(screen); + if (!res) { + WLOGE("RemoveFromGroupLocked. remove screen:%{public}" PRIu64" failed from screenGroup:%{public}" PRIu64".", + screen->screenId_, screen->groupSmsId_); + return false; + } + if (screenGroup->GetChildCount() == 0) { + // Group removed, need to do something. + smsScreenGroupMap_.erase(screenGroup->screenId_); + screenSessionMap_.erase(screenGroup->screenId_); + } + return true; +} + +DMError ScreenSessionManager::SetMirror(ScreenId screenId, std::vector screens) +{ + WLOGI("SetMirror, screenId:%{public}" PRIu64"", screenId); + sptr screen = GetAbstractScreen(screenId); + if (screen == nullptr || screen->type_ != ScreenType::REAL) { + WLOGFE("screen is nullptr, or screenType is not real."); + return DMError::DM_ERROR_NULLPTR; + } + WLOGFD("GetAbstractScreenGroup start"); + auto group = GetAbstractScreenGroup(screen->groupSmsId_); + if (group == nullptr) { + //std::lock_guard lock(mutex_); + group = AddToGroupLocked(screen); + if (group == nullptr) { + WLOGFE("group is nullptr"); + return DMError::DM_ERROR_NULLPTR; + } + NotifyScreenGroupChanged(screen->ConvertToScreenInfo(), ScreenGroupChangeEvent::ADD_TO_GROUP); + // if (group != nullptr && abstractScreenCallback_ != nullptr) { + // abstractScreenCallback_->onConnect_(screen); + // } + } + WLOGFD("GetAbstractScreenGroup end"); + Point point; + std::vector startPoints; + startPoints.insert(startPoints.begin(), screens.size(), point); + bool filterMirroredScreen = + group->combination_ == ScreenCombination::SCREEN_MIRROR && group->mirrorScreenId_ == screen->screenId_; + group->mirrorScreenId_ = screen->screenId_; + ChangeScreenGroup(group, screens, startPoints, filterMirroredScreen, ScreenCombination::SCREEN_MIRROR); + WLOGFI("SetMirror success"); + return DMError::DM_OK; +} + +sptr ScreenSessionManager::GetAbstractScreenGroup(ScreenId smsScreenId) +{ + //std::lock_guard lock(mutex_); + auto iter = smsScreenGroupMap_.find(smsScreenId); + if (iter == smsScreenGroupMap_.end()) { + WLOGE("did not find screen:%{public}" PRIu64"", smsScreenId); + return nullptr; + } + return iter->second; +} + +void ScreenSessionManager::ChangeScreenGroup(sptr group, const std::vector& screens, + const std::vector& startPoints, bool filterScreen, ScreenCombination combination) +{ + std::map removeChildResMap; + std::vector addScreens; + std::vector addChildPos; + //std::lock_guard lock(mutex_); + for (uint64_t i = 0; i != screens.size(); i++) { + ScreenId screenId = screens[i]; + WLOGFI("ScreenId: %{public}" PRIu64"", screenId); + auto screen = GetAbstractScreen(screenId); + if (screen == nullptr) { + WLOGFE("screen:%{public}" PRIu64" is nullptr", screenId); + continue; + } + WLOGFI("Screen->groupDmsId_: %{public}" PRIu64"", screen->groupSmsId_); + if (filterScreen && screen->groupSmsId_ == group->screenId_ && group->HasChild(screen->screenId_)) { + continue; + } + // if (abstractScreenCallback_ != nullptr && CheckScreenInScreenGroup(screen)) { + // abstractScreenCallback_->onDisconnect_(screen); + // } + auto originGroup = RemoveFromGroupLocked(screen); + addChildPos.emplace_back(startPoints[i]); + removeChildResMap[screenId] = originGroup != nullptr; + addScreens.emplace_back(screenId); + } + group->combination_ = combination; + AddScreenToGroup(group, addScreens, addChildPos, removeChildResMap); +} + +void ScreenSessionManager::AddScreenToGroup(sptr group, + const std::vector& addScreens, const std::vector& addChildPos, + std::map& removeChildResMap) +{ + std::vector> addToGroup; + std::vector> removeFromGroup; + std::vector> changeGroup; + for (uint64_t i = 0; i != addScreens.size(); i++) { + ScreenId screenId = addScreens[i]; + sptr screen = GetAbstractScreen(screenId); + if (screen == nullptr) { + continue; + } + Point expandPoint = addChildPos[i]; + WLOGFI("screenId: %{public}" PRIu64", Point: %{public}d, %{public}d", + screen->screenId_, expandPoint.posX_, expandPoint.posY_); + bool addChildRes = group->AddChild(screen, expandPoint); + if (removeChildResMap[screenId] && addChildRes) { + changeGroup.emplace_back(screen->ConvertToScreenInfo()); + WLOGFD("changeGroup"); + } else if (removeChildResMap[screenId]) { + WLOGFD("removeChild"); + removeFromGroup.emplace_back(screen->ConvertToScreenInfo()); + } else if (addChildRes) { + WLOGFD("AddChild"); + addToGroup.emplace_back(screen->ConvertToScreenInfo()); + } else { + WLOGFD("default, AddChild failed"); + } + // if (abstractScreenCallback_ != nullptr) { + // abstractScreenCallback_->onConnect_(screen); + // } + //OnScreenChange(screenId, ScreenEvent::CONNECTED); + // if (rSScreenChangeListener_ != nullptr) { + // rSScreenChangeListener_->onConnected_(); + // } + } + + NotifyScreenGroupChanged(removeFromGroup, ScreenGroupChangeEvent::REMOVE_FROM_GROUP); + NotifyScreenGroupChanged(changeGroup, ScreenGroupChangeEvent::CHANGE_GROUP); + NotifyScreenGroupChanged(addToGroup, ScreenGroupChangeEvent::ADD_TO_GROUP); +} + +void ScreenSessionManager::RemoveVirtualScreenFromGroup(std::vector screens) +{ + WLOGFE("SCB: ScreenSessionManager::RemoveVirtualScreenFromGroup enter!"); + if (screens.empty()) { + return; + } + std::vector> removeFromGroup; + for (ScreenId screenId : screens) { + auto screen = GetAbstractScreen(screenId); + if (screen == nullptr || screen->type_ != ScreenType::VIRTUAL) { + continue; + } + auto originGroup = GetAbstractScreenGroup(screen->groupSmsId_); + if (originGroup == nullptr) { + continue; + } + if (!originGroup->HasChild(screenId)) { + continue; + } + // if (abstractScreenCallback_ != nullptr && CheckScreenInScreenGroup(screen)) { + // abstractScreenCallback_->onDisconnect_(screen); + // } + RemoveFromGroupLocked(screen); + removeFromGroup.emplace_back(screen->ConvertToScreenInfo()); + } + NotifyScreenGroupChanged(removeFromGroup, ScreenGroupChangeEvent::REMOVE_FROM_GROUP); +} + +const std::shared_ptr& ScreenSessionManager::GetRSDisplayNodeByScreenId(ScreenId smsScreenId) const +{ + static std::shared_ptr notFound = nullptr; + sptr screen = GetAbstractScreen(smsScreenId); + if (screen == nullptr) { + WLOGFE("SCB: ScreenSessionManager::GetRSDisplayNodeByScreenId screen == nullptr!"); + return notFound; + } + if (screen->displayNode_ == nullptr) { + WLOGFE("SCB: ScreenSessionManager::GetRSDisplayNodeByScreenId displayNode_ == nullptr!"); + return notFound; + } + WLOGI("GetRSDisplayNodeByScreenId: screen: %{public}" PRIu64", nodeId: %{public}" PRIu64" ", + screen->screenId_, screen->displayNode_->GetId()); + return screen->displayNode_; +} + +std::shared_ptr ScreenSessionManager::GetScreenSnapshot(DisplayId displayId) +{ + WLOGFE("SCB: ScreenSessionManager::GetScreenSnapshot ENTER!"); + // sptr abstractDisplay = GetAbstractDisplay(displayId); + // if (abstractDisplay == nullptr) { + // WLOGFE("GetScreenSnapshot: GetAbstractDisplay failed"); + // return nullptr; + // } + // ScreenId dmsScreenId = abstractDisplay->GetAbstractScreenId(); + ScreenId screenId = SCREEN_ID_INVALID; + std::shared_ptr displayNode = nullptr; + for (auto sessionIt : screenSessionMap_) { + auto screenSession = sessionIt.second; + sptr displayInfo = screenSession->ConvertToDisplayInfo(); + WLOGI("SCB: ScreenSessionManager::GetScreenSnapshot: displayId %{public}" PRIu64"", displayInfo->GetDisplayId()); + if (displayId == displayInfo->GetDisplayId()) { + displayNode = screenSession->displayNode_; + screenId = sessionIt.first; + break; + } + } + if (screenId == SCREEN_ID_INVALID) { + WLOGFE("SCB: ScreenSessionManager::GetScreenSnapshot screenId == SCREEN_ID_INVALID!"); + return nullptr; + } + if (displayNode == nullptr) { + WLOGFE("SCB: ScreenSessionManager::GetScreenSnapshot displayNode == nullptr!"); + return nullptr; + } + // WLOGI("SCB: GetScreenSnapshot: screen: %{public}" PRIu64" ",screenId); + // std::shared_ptr displayNode = GetRSDisplayNodeByScreenId(screenId); + + // //std::lock_guard lock(mutex_); + std::shared_ptr callback = std::make_shared(); + rsInterface_.TakeSurfaceCapture(displayNode, callback); + std::shared_ptr screenshot = callback->GetResult(2000); // wait for <= 2000ms + if (screenshot == nullptr) { + WLOGFE("SCB: Failed to get pixelmap from RS, return nullptr!"); + } + + // notify dm listener + sptr snapshotInfo = new ScreenshotInfo(); + snapshotInfo->SetTrigger(SysCapUtil::GetClientName()); + snapshotInfo->SetDisplayId(displayId); + OnScreenshot(snapshotInfo); + + return screenshot; + //return nullptr; +} + +std::shared_ptr ScreenSessionManager::GetDisplaySnapshot(DisplayId displayId, DmErrorCode* errorCode) +{ + WLOGFE("SCB: ScreenSessionManager::GetDisplaySnapshot ENTER!"); + //HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:GetDisplaySnapshot(%" PRIu64")", displayId); + // if (Permission::CheckCallingPermission(SCREEN_CAPTURE_PERMISSION) || + // Permission::IsStartByHdcd()) { + auto res = GetScreenSnapshot(displayId); + if (res != nullptr) { + //NotifyScreenshot(displayId); + } + return res; + // } + //return nullptr; +} + +bool ScreenSessionManager::OnRemoteDied(const sptr& agent) +{ + if (agent == nullptr) { + return false; + } + //std::lock_guard lock(mutex_); + auto 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; +} + +DMError ScreenSessionManager::RegisterDisplayManagerAgent( + const sptr& displayManagerAgent, DisplayManagerAgentType type) +{ + if (type == DisplayManagerAgentType::SCREEN_EVENT_LISTENER && !Permission::IsSystemCalling() + && !Permission::IsStartByHdcd()) { + WLOGFE("register display manager agent permission denied!"); + //return DMError::DM_ERROR_NOT_SYSTEM_APP; + } + if ((displayManagerAgent == nullptr) || (displayManagerAgent->AsObject() == nullptr)) { + WLOGFE("displayManagerAgent invalid"); + return DMError::DM_ERROR_NULLPTR; + } + + return dmAgentContainer_.RegisterAgent(displayManagerAgent, type) ? DMError::DM_OK :DMError::DM_ERROR_NULLPTR; +} + +DMError ScreenSessionManager::UnregisterDisplayManagerAgent( + const sptr& displayManagerAgent, DisplayManagerAgentType type) +{ + if (type == DisplayManagerAgentType::SCREEN_EVENT_LISTENER && !Permission::IsSystemCalling() + && !Permission::IsStartByHdcd()) { + WLOGFE("unregister display manager agent permission denied!"); + //return DMError::DM_ERROR_NOT_SYSTEM_APP; + } + if ((displayManagerAgent == nullptr) || (displayManagerAgent->AsObject() == nullptr)) { + WLOGFE("displayManagerAgent invalid"); + return DMError::DM_ERROR_NULLPTR; + } + + return dmAgentContainer_.UnregisterAgent(displayManagerAgent, type) ? DMError::DM_OK :DMError::DM_ERROR_NULLPTR; +} + +std::vector ScreenSessionManager::GetAllValidScreenIds(const std::vector& screenIds) const +{ + //std::lock_guard lock(mutex_); + std::vector validScreenIds; + for (ScreenId screenId : screenIds) { + auto screenIdIter = std::find(validScreenIds.begin(), validScreenIds.end(), screenId); + if (screenIdIter != validScreenIds.end()) { + continue; + } + auto iter = screenSessionMap_.find(screenId); + if (iter != screenSessionMap_.end() && iter->second->type_ != ScreenType::UNDEFINED) { + validScreenIds.emplace_back(screenId); + } + } + return validScreenIds; +} + +sptr ScreenSessionManager::GetScreenGroupInfoById(ScreenId screenId) +{ + auto screenSessionGroup = GetAbstractScreenGroup(screenId); + if (screenSessionGroup == nullptr) { + WLOGE("SCB: ScreenSessionManager::GetScreenGroupInfoById cannot find screenGroupInfo: %{public}" PRIu64"", screenId); + return nullptr; + } + return screenSessionGroup->ConvertToScreenGroupInfo(); +} + +void ScreenSessionManager::NotifyScreenConnected(sptr screenInfo) +{ + WLOGFE("SCB: NotifyScreenConnected ENTER"); + if (screenInfo == nullptr) { + WLOGFE("SCB: NotifyScreenConnected error, screenInfo is nullptr."); + return; + } + auto task = [=] { + WLOGFI("SCB: NotifyScreenConnected, screenId:%{public}" PRIu64"", screenInfo->GetScreenId()); + OnScreenConnect(screenInfo); + }; + controllerHandler_->PostTask(task, AppExecFwk::EventQueue::Priority::HIGH); +} + +void ScreenSessionManager::NotifyScreenDisconnected(ScreenId screenId) +{ + WLOGFE("SCB: NotifyScreenDisconnected ENTER"); + auto task = [=] { + WLOGFI("NotifyScreenDisconnected, screenId:%{public}" PRIu64"", screenId); + OnScreenDisconnect(screenId); + }; + controllerHandler_->PostTask(task, AppExecFwk::EventQueue::Priority::HIGH); +} + +void ScreenSessionManager::NotifyScreenGroupChanged( + const sptr& screenInfo, ScreenGroupChangeEvent event) +{ + WLOGFE("SCB: NotifyScreenGroupChanged ENTER"); + if (screenInfo == nullptr) { + WLOGFE("screenInfo is nullptr."); + return; + } + std::string trigger = SysCapUtil::GetClientName(); + auto task = [=] { + WLOGFI("SCB: screenId:%{public}" PRIu64", trigger:[%{public}s]", screenInfo->GetScreenId(), trigger.c_str()); + OnScreenGroupChange(trigger, screenInfo, event); + }; + controllerHandler_->PostTask(task, AppExecFwk::EventQueue::Priority::HIGH); +} + +void ScreenSessionManager::NotifyScreenGroupChanged( + const std::vector>& screenInfo, ScreenGroupChangeEvent event) +{ + WLOGFE("SCB: NotifyScreenGroupChanged ENTER"); + if (screenInfo.empty()) { + return; + } + std::string trigger = SysCapUtil::GetClientName(); + auto task = [=] { + WLOGFI("SCB: trigger:[%{public}s]", trigger.c_str()); + OnScreenGroupChange(trigger, screenInfo, event); + }; + controllerHandler_->PostTask(task, AppExecFwk::EventQueue::Priority::HIGH); +} + +void ScreenSessionManager::OnScreenGroupChange(const std::string& trigger, + const sptr& screenInfo, ScreenGroupChangeEvent groupEvent) +{ + WLOGFE("SCB: OnScreenGroupChange ENTER"); + if (screenInfo == nullptr) { + return; + } + std::vector> screenInfos; + screenInfos.push_back(screenInfo); + OnScreenGroupChange(trigger, screenInfos, groupEvent); +} + +void ScreenSessionManager::OnScreenGroupChange(const std::string& trigger, + const std::vector>& screenInfos, ScreenGroupChangeEvent groupEvent) +{ + WLOGFE("SCB: OnScreenGroupChange ENTER"); + auto agents = dmAgentContainer_.GetAgentsByType(DisplayManagerAgentType::SCREEN_EVENT_LISTENER); + std::vector> infos; + for (auto& screenInfo : screenInfos) { + if (screenInfo != nullptr) { + infos.emplace_back(screenInfo); + } + } + if (agents.empty() || infos.empty()) { + return; + } + for (auto& agent : agents) { + agent->OnScreenGroupChange(trigger, infos, groupEvent); + } +} + +void ScreenSessionManager::OnScreenConnect(const sptr screenInfo) +{ + WLOGFE("SCB: OnScreenConnect ENTER"); + if (screenInfo == nullptr) { + return; + } + auto agents = dmAgentContainer_.GetAgentsByType(DisplayManagerAgentType::SCREEN_EVENT_LISTENER); + if (agents.empty()) { + return; + } + WLOGFI("SCB: OnScreenConnect"); + for (auto& agent : agents) { + agent->OnScreenConnect(screenInfo); + } +} + +void ScreenSessionManager::OnScreenDisconnect(ScreenId screenId) +{ + WLOGFE("SCB: OnScreenDISConnect ENTER"); + auto agents = dmAgentContainer_.GetAgentsByType(DisplayManagerAgentType::SCREEN_EVENT_LISTENER); + if (agents.empty()) { + return; + } + WLOGFI("SCB: OnScreenDisconnect"); + for (auto& agent : agents) { + agent->OnScreenDisconnect(screenId); + } +} + +void ScreenSessionManager::OnScreenshot(sptr info) +{ + if (info == nullptr) { + return; + } + auto agents = dmAgentContainer_.GetAgentsByType(DisplayManagerAgentType::SCREENSHOT_EVENT_LISTENER); + if (agents.empty()) { + return; + } + WLOGFI("SCB: onScreenshot"); + for (auto& agent : agents) { + agent->OnScreenshot(info); + } +} + } // namespace OHOS::Rosen diff --git a/window_scene/session_manager/src/zidl/screen_session_manager_proxy.cpp b/window_scene/session_manager/src/zidl/screen_session_manager_proxy.cpp index dd120e79474ce1e2b0e93d69cec88a9837487ae1..1ba3f96364716eaa884c168ea366e1482c1e141d 100644 --- a/window_scene/session_manager/src/zidl/screen_session_manager_proxy.cpp +++ b/window_scene/session_manager/src/zidl/screen_session_manager_proxy.cpp @@ -100,4 +100,245 @@ DMError ScreenSessionManagerProxy::UnregisterDisplayManagerAgent(const sptr(reply.ReadInt32()); } +ScreenId ScreenSessionManagerProxy::CreateVirtualScreen(VirtualScreenOption virtualOption, const sptr& displayManagerAgent) +{ + WLOGFW("SCB: ScreenSessionManagerProxy::CreateVirtualScreen: ENTER"); + sptr remote = Remote(); + if (remote == nullptr) { + WLOGFW("SCB: ScreenSessionManagerProxy::CreateVirtualScreen: remote is nullptr"); + return SCREEN_ID_INVALID; + } + + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("SCB: ScreenSessionManagerProxy::CreateVirtualScreen: WriteInterfaceToken failed"); + return SCREEN_ID_INVALID; + } + bool res = data.WriteString(virtualOption.name_) && data.WriteUint32(virtualOption.width_) && + data.WriteUint32(virtualOption.height_) && data.WriteFloat(virtualOption.density_) && + data.WriteInt32(virtualOption.flags_) && data.WriteBool(virtualOption.isForShot_); + if (virtualOption.surface_ != nullptr && virtualOption.surface_->GetProducer() != nullptr) { + res = res && + data.WriteBool(true) && + data.WriteRemoteObject(virtualOption.surface_->GetProducer()->AsObject()); + } else { + WLOGFW("SCB: ScreenSessionManagerProxy::CreateVirtualScreen: surface is nullptr"); + res = res && data.WriteBool(false); + } + if (displayManagerAgent != nullptr) { + res = res && + data.WriteRemoteObject(displayManagerAgent); + } + if (!res) { + WLOGFE("SCB: ScreenSessionManagerProxy::Write data failed"); + return SCREEN_ID_INVALID; + } + if (remote->SendRequest(static_cast(DisplayManagerMessage::TRANS_ID_CREATE_VIRTUAL_SCREEN), + data, reply, option) != ERR_NONE) { + WLOGFW("SCB: ScreenSessionManagerProxy::CreateVirtualScreen: SendRequest failed"); + return SCREEN_ID_INVALID; + } + + ScreenId screenId = static_cast(reply.ReadUint64()); + //WLOGFI("SCB: ScreenSessionManagerProxy::CreateVirtualScreen %" PRIu64"", screenId); + return screenId; +} + +DMError ScreenSessionManagerProxy::SetVirtualScreenSurface(ScreenId screenId, sptr surface) +{ + WLOGFW("SCB: ScreenSessionManagerProxy::SetVirtualScreenSurface: ENTER"); + sptr remote = Remote(); + if (remote == nullptr) { + WLOGFW("SCB: ScreenSessionManagerProxy::SetVirtualScreenSurface: remote is nullptr"); + return DMError::DM_ERROR_REMOTE_CREATE_FAILED; + } + + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("SCB: ScreenSessionManagerProxy::SetVirtualScreenSurface: WriteInterfaceToken failed"); + return DMError::DM_ERROR_WRITE_INTERFACE_TOKEN_FAILED; + } + bool res = data.WriteUint64(static_cast(screenId)); + if (surface != nullptr) { + res = res && + data.WriteBool(true) && + data.WriteRemoteObject(surface->AsObject()); + } else { + WLOGFW("SCB: ScreenSessionManagerProxy::SetVirtualScreenSurface: surface is nullptr"); + res = res && data.WriteBool(false); + } + if (!res) { + WLOGFW("SCB: ScreenSessionManagerProxy::SetVirtualScreenSurface: Write screenId/surface failed"); + return DMError::DM_ERROR_IPC_FAILED; + } + if (remote->SendRequest(static_cast(DisplayManagerMessage::TRANS_ID_SET_VIRTUAL_SCREEN_SURFACE), + data, reply, option) != ERR_NONE) { + WLOGFW("SCB: ScreenSessionManagerProxy::SetVirtualScreenSurface: SendRequest failed"); + return DMError::DM_ERROR_IPC_FAILED; + } + return static_cast(reply.ReadInt32()); +} + +DMError ScreenSessionManagerProxy::DestroyVirtualScreen(ScreenId screenId) +{ + WLOGFW("SCB: ScreenSessionManagerProxy::DestroyVirtualScreen: ENTER"); + sptr remote = Remote(); + if (remote == nullptr) { + WLOGFW("SCB: ScreenSessionManagerProxy::DestroyVirtualScreen: remote is nullptr"); + return DMError::DM_ERROR_REMOTE_CREATE_FAILED; + } + + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("SCB: ScreenSessionManagerProxy::DestroyVirtualScreen: WriteInterfaceToken failed"); + return DMError::DM_ERROR_WRITE_INTERFACE_TOKEN_FAILED; + } + if (!data.WriteUint64(static_cast(screenId))) { + WLOGFW("SCB: ScreenSessionManagerProxy::DestroyVirtualScreen: WriteUint64 screenId failed"); + return DMError::DM_ERROR_IPC_FAILED; + } + if (remote->SendRequest(static_cast(DisplayManagerMessage::TRANS_ID_DESTROY_VIRTUAL_SCREEN), + data, reply, option) != ERR_NONE) { + WLOGFW("SCB: ScreenSessionManagerProxy::DestroyVirtualScreen: SendRequest failed"); + return DMError::DM_ERROR_IPC_FAILED; + } + return static_cast(reply.ReadInt32()); +} + +DMError ScreenSessionManagerProxy::MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenIds, ScreenId& screenGroupId) +{ + WLOGFW("SCB: ScreenSessionManagerProxy::MakeMirror: ENTER"); + sptr remote = Remote(); + if (remote == nullptr) { + WLOGFW("SCB: ScreenSessionManagerProxy::MakeMirror: create mirror fail: remote is null"); + return DMError::DM_ERROR_NULLPTR; + } + + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("SCB: ScreenSessionManagerProxy::MakeMirror: create mirror fail: WriteInterfaceToken failed"); + return DMError::DM_ERROR_WRITE_INTERFACE_TOKEN_FAILED; + } + bool res = data.WriteUint64(static_cast(mainScreenId)) && + data.WriteUInt64Vector(mirrorScreenIds); + if (!res) { + WLOGFE("SCB: ScreenSessionManagerProxy::MakeMirror: create mirror fail: data write failed"); + return DMError::DM_ERROR_IPC_FAILED; + } + if (remote->SendRequest(static_cast(DisplayManagerMessage::TRANS_ID_SCREEN_MAKE_MIRROR), + data, reply, option) != ERR_NONE) { + WLOGFW("SCB: ScreenSessionManagerProxy::MakeMirror: create mirror fail: SendRequest failed"); + return DMError::DM_ERROR_IPC_FAILED; + } + DMError ret = static_cast(reply.ReadInt32()); + screenGroupId = static_cast(reply.ReadUint64()); + return ret; +} + +sptr ScreenSessionManagerProxy::GetScreenGroupInfoById(ScreenId screenId) +{ + WLOGFW("SCB: ScreenSessionManagerProxy::GetScreenGroupInfoById: ENTER!"); + sptr remote = Remote(); + if (remote == nullptr) { + WLOGFW("SCB: ScreenSessionManagerProxy::GetScreenGroupInfoById: remote is nullptr"); + return nullptr; + } + + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("SCB: ScreenSessionManagerProxy::GetScreenGroupInfoById: WriteInterfaceToken failed"); + return nullptr; + } + if (!data.WriteUint64(screenId)) { + WLOGFE("SCB: ScreenSessionManagerProxy::GetScreenGroupInfoById: Write screenId failed"); + return nullptr; + } + if (remote->SendRequest(static_cast(DisplayManagerMessage::TRANS_ID_GET_SCREEN_GROUP_INFO_BY_ID), + data, reply, option) != ERR_NONE) { + WLOGFW("SCB: ScreenSessionManagerProxy::GetScreenGroupInfoById: SendRequest failed"); + return nullptr; + } + + sptr info = reply.ReadStrongParcelable(); + if (info == nullptr) { + WLOGFW("SCB: ScreenSessionManagerProxy::GetScreenGroupInfoById SendRequest nullptr."); + return nullptr; + } + return info; +} + +void ScreenSessionManagerProxy::RemoveVirtualScreenFromGroup(std::vector screens) +{ + WLOGFW("SCB: ScreenSessionManagerProxy::RemoveVirtualScreenFromGroup: ENTER!"); + sptr remote = Remote(); + if (remote == nullptr) { + WLOGFW("SCB: ScreenSessionManagerProxy::RemoveVirtualScreenFromGroup:remote is null"); + return; + } + + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("SCB: ScreenSessionManagerProxy::RemoveVirtualScreenFromGroup: WriteInterfaceToken failed"); + return; + } + bool res = data.WriteUInt64Vector(screens); + if (!res) { + WLOGFE("SCB: ScreenSessionManagerProxy::RemoveVirtualScreenFromGroup: write screens failed."); + return; + } + if (remote->SendRequest(static_cast( + DisplayManagerMessage::TRANS_ID_REMOVE_VIRTUAL_SCREEN_FROM_SCREEN_GROUP), + data, reply, option) != ERR_NONE) { + WLOGFW("SCB: ScreenSessionManagerProxy::RemoveVirtualScreenFromGroup:: SendRequest failed"); + } +} + +std::shared_ptr ScreenSessionManagerProxy::GetDisplaySnapshot(DisplayId displayId, DmErrorCode* errorCode) +{ + WLOGFW("SCB: ScreenSessionManagerProxy::GetDisplaySnapshot enter"); + sptr remote = Remote(); + if (remote == nullptr) { + WLOGFW("SCB: ScreenSessionManagerProxy::GetDisplaySnapshot: remote is nullptr"); + return nullptr; + } + + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("SCB: ScreenSessionManagerProxy::GetDisplaySnapshot: WriteInterfaceToken failed"); + return nullptr; + } + + if (!data.WriteUint64(displayId)) { + WLOGFE("SCB: ScreenSessionManagerProxy::GetDisplaySnapshot: Write displayId failed"); + return nullptr; + } + + if (remote->SendRequest(static_cast(DisplayManagerMessage::TRANS_ID_GET_DISPLAY_SNAPSHOT), + data, reply, option) != ERR_NONE) { + WLOGFW("SCB: ScreenSessionManagerProxy::GetDisplaySnapshot: SendRequest failed"); + return nullptr; + } + + std::shared_ptr pixelMap(reply.ReadParcelable()); + if (pixelMap == nullptr) { + WLOGFW("SCB: ScreenSessionManagerProxy::GetDisplaySnapshot: SendRequest nullptr."); + return nullptr; + } + return pixelMap; +} + } // namespace OHOS::Rosen diff --git a/window_scene/session_manager/src/zidl/screen_session_manager_stub.cpp b/window_scene/session_manager/src/zidl/screen_session_manager_stub.cpp index 3dd689c6af1e2a0ba046311b6a1abc7166426fd2..9f87ee66e2fbed5429677b248124df7bc21ef869 100644 --- a/window_scene/session_manager/src/zidl/screen_session_manager_stub.cpp +++ b/window_scene/session_manager/src/zidl/screen_session_manager_stub.cpp @@ -51,6 +51,93 @@ int32_t ScreenSessionManagerStub::OnRemoteRequest(uint32_t code, MessageParcel& reply.WriteInt32(static_cast(ret)); break; } + case DisplayManagerMessage::TRANS_ID_CREATE_VIRTUAL_SCREEN: { + WLOGFW("SCB: ScreenSessionManagerStub::OnRemoteRequest::CreateVirtualScreen"); + std::string name = data.ReadString(); + uint32_t width = data.ReadUint32(); + uint32_t height = data.ReadUint32(); + float density = data.ReadFloat(); + int32_t flags = data.ReadInt32(); + bool isForShot = data.ReadBool(); + bool isSurfaceValid = data.ReadBool(); + sptr surface = nullptr; + if (isSurfaceValid) { + sptr surfaceObject = data.ReadRemoteObject(); + sptr bp = iface_cast(surfaceObject); + surface = Surface::CreateSurfaceAsProducer(bp); + } + sptr virtualScreenAgent = data.ReadRemoteObject(); + VirtualScreenOption virScrOption = { + .name_ = name, + .width_ = width, + .height_ = height, + .density_ = density, + .surface_ = surface, + .flags_ = flags, + .isForShot_ = isForShot + }; + ScreenId screenId = CreateVirtualScreen(virScrOption, virtualScreenAgent); + reply.WriteUint64(static_cast(screenId)); + break; + } + case DisplayManagerMessage::TRANS_ID_SET_VIRTUAL_SCREEN_SURFACE: { + WLOGFW("SCB: ScreenSessionManagerStub::OnRemoteRequest::SetVirtualScreenSurface"); + ScreenId screenId = static_cast(data.ReadUint64()); + bool isSurfaceValid = data.ReadBool(); + sptr bp = nullptr; + if (isSurfaceValid) { + sptr surfaceObject = data.ReadRemoteObject(); + bp = iface_cast(surfaceObject); + } + DMError result = SetVirtualScreenSurface(screenId, bp); + reply.WriteInt32(static_cast(result)); + break; + } + case DisplayManagerMessage::TRANS_ID_DESTROY_VIRTUAL_SCREEN: { + WLOGFW("SCB: ScreenSessionManagerStub::OnRemoteRequest::DestroyVirtualScreen"); + ScreenId screenId = static_cast(data.ReadUint64()); + DMError result = DestroyVirtualScreen(screenId); + reply.WriteInt32(static_cast(result)); + break; + } + case DisplayManagerMessage::TRANS_ID_SCREEN_MAKE_MIRROR: { + WLOGFW("SCB: ScreenSessionManagerStub::OnRemoteRequest::MakeMirror"); + ScreenId mainScreenId = static_cast(data.ReadUint64()); + std::vector mirrorScreenId; + if (!data.ReadUInt64Vector(&mirrorScreenId)) { + WLOGE("SCB: ScreenSessionManagerStub::MakeMirror: fail to receive mirror screen in stub. screen:%{public}" PRIu64"", mainScreenId); + break; + } + ScreenId screenGroupId = INVALID_SCREEN_ID; + DMError ret = MakeMirror(mainScreenId, mirrorScreenId, screenGroupId); + reply.WriteInt32(static_cast(ret)); + reply.WriteUint64(static_cast(screenGroupId)); + break; + } + case DisplayManagerMessage::TRANS_ID_GET_SCREEN_GROUP_INFO_BY_ID: { + WLOGFW("SCB: ScreenSessionManagerStub::OnRemoteRequest::GetScreenGroupInfoById"); + ScreenId screenId = static_cast(data.ReadUint64()); + auto screenGroupInfo = GetScreenGroupInfoById(screenId); + reply.WriteStrongParcelable(screenGroupInfo); + break; + } + case DisplayManagerMessage::TRANS_ID_REMOVE_VIRTUAL_SCREEN_FROM_SCREEN_GROUP: { + WLOGFW("SCB: ScreenSessionManagerStub::OnRemoteRequest::RemoveVirtualScreenFromGroup"); + std::vector screenId; + if (!data.ReadUInt64Vector(&screenId)) { + WLOGE("fail to receive screens in stub."); + break; + } + RemoveVirtualScreenFromGroup(screenId); + break; + } + case DisplayManagerMessage::TRANS_ID_GET_DISPLAY_SNAPSHOT: { + WLOGFW("SCB: ScreenSessionManagerStub::OnRemoteRequest::GetDisplaySnapshot"); + DisplayId displayId = data.ReadUint64(); + std::shared_ptr displaySnapshot = GetDisplaySnapshot(displayId); + reply.WriteParcelable(displaySnapshot == nullptr ? nullptr : displaySnapshot.get()); + break; + } default: WLOGFW("unknown transaction code"); return IPCObjectStub::OnRemoteRequest(code, data, reply, option);