1/*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15#include "screen_manager_lite.h"
16#include <cinttypes>
17#include "display_manager_adapter_lite.h"
18#include "display_manager_agent_default.h"
19#include "singleton_delegator.h"
20#include "window_manager_hilog.h"
21
22namespace OHOS::Rosen {
23namespace {
24    constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "ScreenManagerLite"};
25}
26
27/*
28 * used by powermgr
29 */
30class ScreenManagerLite::Impl : public RefBase {
31public:
32    Impl() = default;
33    ~Impl();
34
35    static inline SingletonDelegator<ScreenManagerLite> delegator;
36    DMError RegisterScreenListener(sptr<IScreenListener> listener);
37    DMError UnregisterScreenListener(sptr<IScreenListener> listener);
38    DMError RegisterDisplayManagerAgent();
39    DMError UnregisterDisplayManagerAgent();
40    void OnRemoteDied();
41
42private:
43    void NotifyScreenConnect(sptr<ScreenInfo> info);
44    void NotifyScreenDisconnect(ScreenId);
45    void NotifyScreenChange(const sptr<ScreenInfo>& screenInfo);
46
47    class ScreenManagerListener;
48    sptr<ScreenManagerListener> screenManagerListener_;
49    std::mutex mutex_;
50    std::set<sptr<IScreenListener>> screenListeners_;
51};
52
53class ScreenManagerLite::Impl::ScreenManagerListener : public DisplayManagerAgentDefault {
54public:
55    explicit ScreenManagerListener(sptr<Impl> impl) : pImpl_(impl)
56    {
57    }
58
59    void OnScreenConnect(sptr<ScreenInfo> screenInfo)
60    {
61        if (screenInfo == nullptr || screenInfo->GetScreenId() == SCREEN_ID_INVALID) {
62            WLOGFE("OnScreenConnect, screenInfo is invalid.");
63            return;
64        }
65        if (pImpl_ == nullptr) {
66            WLOGFE("OnScreenConnect, impl is nullptr.");
67            return;
68        }
69        std::lock_guard<std::mutex> lock(pImpl_->mutex_);
70        for (auto listener : pImpl_->screenListeners_) {
71            listener->OnConnect(screenInfo->GetScreenId());
72        }
73    };
74
75    void OnScreenDisconnect(ScreenId screenId)
76    {
77        if (screenId == SCREEN_ID_INVALID) {
78            WLOGFE("OnScreenDisconnect, screenId is invalid.");
79            return;
80        }
81        if (pImpl_ == nullptr) {
82            WLOGFE("OnScreenDisconnect, impl is nullptr.");
83            return;
84        }
85        std::lock_guard<std::mutex> lock(pImpl_->mutex_);
86        for (auto listener : pImpl_->screenListeners_) {
87            listener->OnDisconnect(screenId);
88        }
89    };
90
91    void OnScreenChange(const sptr<ScreenInfo>& screenInfo, ScreenChangeEvent event)
92    {
93        if (screenInfo == nullptr) {
94            WLOGFE("OnScreenChange, screenInfo is null.");
95            return;
96        }
97        if (pImpl_ == nullptr) {
98            WLOGFE("OnScreenChange, impl is nullptr.");
99            return;
100        }
101        WLOGFD("OnScreenChange. event %{public}u", event);
102        std::lock_guard<std::mutex> lock(pImpl_->mutex_);
103        for (auto listener: pImpl_->screenListeners_) {
104            listener->OnChange(screenInfo->GetScreenId());
105        }
106    };
107private:
108    sptr<Impl> pImpl_;
109};
110
111WM_IMPLEMENT_SINGLE_INSTANCE(ScreenManagerLite)
112
113ScreenManagerLite::ScreenManagerLite()
114{
115    pImpl_ = new Impl();
116    WLOGFD("Create ScreenManagerLite instance");
117}
118
119ScreenManagerLite::~ScreenManagerLite()
120{
121    WLOGFD("Destroy ScreenManagerLite instance");
122}
123
124ScreenManagerLite::Impl::~Impl()
125{
126    std::lock_guard<std::mutex> lock(mutex_);
127    UnregisterDisplayManagerAgent();
128}
129
130DMError ScreenManagerLite::Impl::RegisterDisplayManagerAgent()
131{
132    DMError regSucc = DMError::DM_OK;
133    if (screenManagerListener_ == nullptr) {
134        screenManagerListener_ = new ScreenManagerListener(this);
135        regSucc = SingletonContainer::Get<ScreenManagerAdapterLite>().RegisterDisplayManagerAgent(
136            screenManagerListener_, DisplayManagerAgentType::SCREEN_EVENT_LISTENER);
137        if (regSucc != DMError::DM_OK) {
138            screenManagerListener_ = nullptr;
139            WLOGFW("RegisterDisplayManagerAgent failed !");
140        }
141    }
142    return regSucc;
143}
144
145DMError ScreenManagerLite::Impl::UnregisterDisplayManagerAgent()
146{
147    DMError unRegSucc = DMError::DM_OK;
148    if (screenManagerListener_ != nullptr) {
149        unRegSucc = SingletonContainer::Get<ScreenManagerAdapterLite>().UnregisterDisplayManagerAgent(
150            screenManagerListener_, DisplayManagerAgentType::SCREEN_EVENT_LISTENER);
151        screenManagerListener_ = nullptr;
152        if (unRegSucc != DMError::DM_OK) {
153            WLOGFW("UnregisterDisplayManagerAgent failed!");
154        }
155    }
156    return unRegSucc;
157}
158
159DMError ScreenManagerLite::Impl::RegisterScreenListener(sptr<IScreenListener> listener)
160{
161    std::lock_guard<std::mutex> lock(mutex_);
162    DMError regSucc = RegisterDisplayManagerAgent();
163    if (regSucc == DMError::DM_OK) {
164        screenListeners_.insert(listener);
165    }
166    return regSucc;
167}
168
169DMError ScreenManagerLite::RegisterScreenListener(sptr<IScreenListener> listener)
170{
171    if (listener == nullptr) {
172        WLOGFE("RegisterScreenListener listener is nullptr.");
173        return DMError::DM_ERROR_NULLPTR;
174    }
175    return pImpl_->RegisterScreenListener(listener);
176}
177
178DMError ScreenManagerLite::Impl::UnregisterScreenListener(sptr<IScreenListener> listener)
179{
180    std::lock_guard<std::mutex> lock(mutex_);
181    auto iter = std::find(screenListeners_.begin(), screenListeners_.end(), listener);
182    if (iter == screenListeners_.end()) {
183        WLOGFE("could not find this listener");
184        return DMError::DM_ERROR_NULLPTR;
185    }
186    screenListeners_.erase(iter);
187    return UnregisterDisplayManagerAgent();
188}
189
190DMError ScreenManagerLite::UnregisterScreenListener(sptr<IScreenListener> listener)
191{
192    if (listener == nullptr) {
193        WLOGFE("UnregisterScreenListener listener is nullptr.");
194        return DMError::DM_ERROR_NULLPTR;
195    }
196    return pImpl_->UnregisterScreenListener(listener);
197}
198
199bool ScreenManagerLite::SetSpecifiedScreenPower(ScreenId screenId,
200    ScreenPowerState state, PowerStateChangeReason reason)
201{
202    WLOGFI("screenId:%{public}" PRIu64 ", state:%{public}u, reason:%{public}u", screenId, state, reason);
203    return SingletonContainer::Get<ScreenManagerAdapterLite>().SetSpecifiedScreenPower(screenId, state, reason);
204}
205
206bool ScreenManagerLite::SetScreenPowerForAll(ScreenPowerState state, PowerStateChangeReason reason)
207{
208    WLOGFI("state:%{public}u, reason:%{public}u", state, reason);
209    return SingletonContainer::Get<ScreenManagerAdapterLite>().SetScreenPowerForAll(state, reason);
210}
211
212ScreenPowerState ScreenManagerLite::GetScreenPower(ScreenId dmsScreenId)
213{
214    return SingletonContainer::Get<ScreenManagerAdapterLite>().GetScreenPower(dmsScreenId);
215}
216
217void ScreenManagerLite::Impl::OnRemoteDied()
218{
219    WLOGFD("dms is died");
220    std::lock_guard<std::mutex> lock(mutex_);
221    screenManagerListener_ = nullptr;
222}
223
224void ScreenManagerLite::OnRemoteDied()
225{
226    pImpl_->OnRemoteDied();
227}
228
229} // namespace OHOS::Rosen