/* * Copyright (c) 2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at. * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software, * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "display_manager_lite.h" #include #include #include "display_manager_adapter_lite.h" #include "display_manager_agent_default.h" #include "dm_common.h" #include "singleton_delegator.h" #include "window_manager_hilog.h" namespace OHOS::Rosen { namespace { constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "DisplayManagerLite"}; } WM_IMPLEMENT_SINGLE_INSTANCE(DisplayManagerLite) class DisplayManagerLite::Impl : public RefBase { public: Impl(std::recursive_mutex& mutex) : mutex_(mutex) {} ~Impl(); static inline SingletonDelegator delegator; sptr GetDefaultDisplay(); FoldStatus GetFoldStatus(); FoldDisplayMode GetFoldDisplayMode(); bool IsFoldable(); DMError RegisterDisplayListener(sptr listener); DMError UnregisterDisplayListener(sptr listener); DMError RegisterFoldStatusListener(sptr listener); DMError UnregisterFoldStatusListener(sptr listener); void OnRemoteDied(); private: void NotifyDisplayCreate(sptr info); void NotifyDisplayDestroy(DisplayId); void NotifyDisplayChange(sptr displayInfo); bool UpdateDisplayInfoLocked(sptr); void NotifyFoldStatusChanged(FoldStatus foldStatus); void Clear(); std::map> displayMap_; std::recursive_mutex& mutex_; std::set> displayListeners_; std::set> foldStatusListeners_; class DisplayManagerListener; sptr displayManagerListener_; class DisplayManagerFoldStatusAgent; sptr foldStatusListenerAgent_; }; class DisplayManagerLite::Impl::DisplayManagerListener : public DisplayManagerAgentDefault { public: explicit DisplayManagerListener(sptr impl) : pImpl_(impl) { } void OnDisplayCreate(sptr displayInfo) override { if (displayInfo == nullptr || displayInfo->GetDisplayId() == DISPLAY_ID_INVALID) { WLOGFE("onDisplayCreate: displayInfo is nullptr"); return; } if (pImpl_ == nullptr) { WLOGFE("onDisplayCreate: pImpl_ is nullptr"); return; } pImpl_->NotifyDisplayCreate(displayInfo); std::set> displayListeners; { std::lock_guard lock(pImpl_->mutex_); displayListeners = pImpl_->displayListeners_; } for (auto listener : displayListeners) { listener->OnCreate(displayInfo->GetDisplayId()); } }; void OnDisplayDestroy(DisplayId displayId) override { if (displayId == DISPLAY_ID_INVALID) { WLOGFE("onDisplayDestroy: displayId is invalid"); return; } if (pImpl_ == nullptr) { WLOGFE("onDisplayDestroy: impl is nullptr"); return; } pImpl_->NotifyDisplayDestroy(displayId); std::set> displayListeners; { std::lock_guard lock(pImpl_->mutex_); displayListeners = pImpl_->displayListeners_; } for (auto listener : displayListeners) { listener->OnDestroy(displayId); } }; void OnDisplayChange(sptr displayInfo, DisplayChangeEvent event) override { if (displayInfo == nullptr || displayInfo->GetDisplayId() == DISPLAY_ID_INVALID) { WLOGFE("onDisplayChange: displayInfo is nullptr"); return; } if (pImpl_ == nullptr) { WLOGFE("onDisplayChange: pImpl_ is nullptr"); return; } WLOGD("onDisplayChange: display %{public}" PRIu64", event %{public}u", displayInfo->GetDisplayId(), event); pImpl_->NotifyDisplayChange(displayInfo); std::set> displayListeners; { std::lock_guard lock(pImpl_->mutex_); displayListeners = pImpl_->displayListeners_; } for (auto listener : displayListeners) { listener->OnChange(displayInfo->GetDisplayId()); } }; private: sptr pImpl_; }; class DisplayManagerLite::Impl::DisplayManagerFoldStatusAgent : public DisplayManagerAgentDefault { public: explicit DisplayManagerFoldStatusAgent(sptr impl) : pImpl_(impl) { } ~DisplayManagerFoldStatusAgent() = default; virtual void NotifyFoldStatusChanged(FoldStatus foldStatus) override { pImpl_->NotifyFoldStatusChanged(foldStatus); } private: sptr pImpl_; }; void DisplayManagerLite::Impl::Clear() { std::lock_guard lock(mutex_); DMError res = DMError::DM_OK; if (displayManagerListener_ != nullptr) { res = SingletonContainer::Get().UnregisterDisplayManagerAgent( displayManagerListener_, DisplayManagerAgentType::DISPLAY_EVENT_LISTENER); } displayManagerListener_ = nullptr; if (res != DMError::DM_OK) { WLOGFW("UnregisterDisplayManagerAgent DISPLAY_EVENT_LISTENER failed"); } } DisplayManagerLite::Impl::~Impl() { Clear(); } DisplayManagerLite::DisplayManagerLite() : pImpl_(new Impl(mutex_)) { } DisplayManagerLite::~DisplayManagerLite() { std::lock_guard lock(mutex_); destroyed_ = true; } DMError DisplayManagerLite::Impl::RegisterDisplayListener(sptr listener) { std::lock_guard lock(mutex_); DMError ret = DMError::DM_OK; if (displayManagerListener_ == nullptr) { displayManagerListener_ = new DisplayManagerListener(this); ret = SingletonContainer::Get().RegisterDisplayManagerAgent( displayManagerListener_, DisplayManagerAgentType::DISPLAY_EVENT_LISTENER); } if (ret != DMError::DM_OK) { WLOGFW("RegisterDisplayManagerAgent failed"); displayManagerListener_ = nullptr; } else { displayListeners_.insert(listener); } return ret; } DMError DisplayManagerLite::RegisterDisplayListener(sptr listener) { if (listener == nullptr) { WLOGFE("RegisterDisplayListener listener is nullptr"); return DMError::DM_ERROR_NULLPTR; } return pImpl_->RegisterDisplayListener(listener); } DMError DisplayManagerLite::Impl::UnregisterDisplayListener(sptr listener) { std::lock_guard lock(mutex_); auto iter = std::find(displayListeners_.begin(), displayListeners_.end(), listener); if (iter == displayListeners_.end()) { WLOGFE("could not find this listener"); return DMError::DM_ERROR_NULLPTR; } displayListeners_.erase(iter); DMError ret = DMError::DM_OK; if (displayListeners_.empty() && displayManagerListener_ != nullptr) { ret = SingletonContainer::Get().UnregisterDisplayManagerAgent( displayManagerListener_, DisplayManagerAgentType::DISPLAY_EVENT_LISTENER); displayManagerListener_ = nullptr; } return ret; } DMError DisplayManagerLite::UnregisterDisplayListener(sptr listener) { if (listener == nullptr) { WLOGFE("UnregisterDisplayListener listener is nullptr"); return DMError::DM_ERROR_NULLPTR; } return pImpl_->UnregisterDisplayListener(listener); } void DisplayManagerLite::Impl::NotifyDisplayCreate(sptr info) { std::lock_guard lock(mutex_); UpdateDisplayInfoLocked(info); } void DisplayManagerLite::Impl::NotifyDisplayDestroy(DisplayId displayId) { WLOGFD("displayId:%{public}" PRIu64".", displayId); std::lock_guard lock(mutex_); displayMap_.erase(displayId); } void DisplayManagerLite::Impl::NotifyDisplayChange(sptr displayInfo) { std::lock_guard lock(mutex_); UpdateDisplayInfoLocked(displayInfo); } bool DisplayManagerLite::Impl::UpdateDisplayInfoLocked(sptr displayInfo) { if (displayInfo == nullptr) { WLOGFE("displayInfo is null"); return false; } DisplayId displayId = displayInfo->GetDisplayId(); WLOGFD("displayId:%{public}" PRIu64".", displayId); if (displayId == DISPLAY_ID_INVALID) { WLOGFE("displayId is invalid"); return false; } auto iter = displayMap_.find(displayId); if (iter != displayMap_.end() && iter->second != nullptr) { WLOGFD("get screen in screen map"); iter->second->UpdateDisplayInfo(displayInfo); return true; } sptr display = new DisplayLite("", displayInfo); displayMap_[displayId] = display; return true; } DMError DisplayManagerLite::RegisterFoldStatusListener(sptr listener) { if (listener == nullptr) { WLOGFE("IFoldStatusListener listener is nullptr."); return DMError::DM_ERROR_NULLPTR; } return pImpl_->RegisterFoldStatusListener(listener); } DMError DisplayManagerLite::Impl::RegisterFoldStatusListener(sptr listener) { std::lock_guard lock(mutex_); DMError ret = DMError::DM_OK; if (foldStatusListenerAgent_ == nullptr) { foldStatusListenerAgent_ = new DisplayManagerFoldStatusAgent(this); ret = SingletonContainer::Get().RegisterDisplayManagerAgent( foldStatusListenerAgent_, DisplayManagerAgentType::FOLD_STATUS_CHANGED_LISTENER); } if (ret != DMError::DM_OK) { WLOGFW("RegisterFoldStatusListener failed !"); foldStatusListenerAgent_ = nullptr; } else { WLOGI("IFoldStatusListener register success"); foldStatusListeners_.insert(listener); } return ret; } DMError DisplayManagerLite::UnregisterFoldStatusListener(sptr listener) { if (listener == nullptr) { WLOGFE("UnregisterFoldStatusListener listener is nullptr."); return DMError::DM_ERROR_NULLPTR; } return pImpl_->UnregisterFoldStatusListener(listener); } DMError DisplayManagerLite::Impl::UnregisterFoldStatusListener(sptr listener) { std::lock_guard lock(mutex_); auto iter = std::find(foldStatusListeners_.begin(), foldStatusListeners_.end(), listener); if (iter == foldStatusListeners_.end()) { WLOGFE("could not find this listener"); return DMError::DM_ERROR_NULLPTR; } foldStatusListeners_.erase(iter); DMError ret = DMError::DM_OK; if (foldStatusListeners_.empty() && foldStatusListenerAgent_ != nullptr) { ret = SingletonContainer::Get().UnregisterDisplayManagerAgent( foldStatusListenerAgent_, DisplayManagerAgentType::FOLD_STATUS_CHANGED_LISTENER); foldStatusListenerAgent_ = nullptr; } return ret; } void DisplayManagerLite::Impl::NotifyFoldStatusChanged(FoldStatus foldStatus) { std::set> foldStatusListeners; { std::lock_guard lock(mutex_); foldStatusListeners = foldStatusListeners_; } for (auto& listener : foldStatusListeners) { listener->OnFoldStatusChanged(foldStatus); } } FoldStatus DisplayManagerLite::GetFoldStatus() { return pImpl_->GetFoldStatus(); } FoldStatus DisplayManagerLite::Impl::GetFoldStatus() { return SingletonContainer::Get().GetFoldStatus(); } sptr DisplayManagerLite::GetDefaultDisplay() { return pImpl_->GetDefaultDisplay(); } sptr DisplayManagerLite::Impl::GetDefaultDisplay() { auto displayInfo = SingletonContainer::Get().GetDefaultDisplayInfo(); if (displayInfo == nullptr) { return nullptr; } auto displayId = displayInfo->GetDisplayId(); std::lock_guard lock(mutex_); if (!UpdateDisplayInfoLocked(displayInfo)) { displayMap_.erase(displayId); return nullptr; } return displayMap_[displayId]; } bool DisplayManagerLite::IsFoldable() { return pImpl_->IsFoldable(); } bool DisplayManagerLite::Impl::IsFoldable() { return SingletonContainer::Get().IsFoldable(); } FoldDisplayMode DisplayManagerLite::GetFoldDisplayMode() { return pImpl_->GetFoldDisplayMode(); } FoldDisplayMode DisplayManagerLite::Impl::GetFoldDisplayMode() { return SingletonContainer::Get().GetFoldDisplayMode(); } void DisplayManagerLite::Impl::OnRemoteDied() { WLOGFI("dms is died"); std::lock_guard lock(mutex_); displayManagerListener_ = nullptr; } void DisplayManagerLite::OnRemoteDied() { pImpl_->OnRemoteDied(); } } // namespace OHOS::Rosen