1e0dac50fSopenharmony_ci/*
2e0dac50fSopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3e0dac50fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4e0dac50fSopenharmony_ci * you may not use this file except in compliance with the License.
5e0dac50fSopenharmony_ci * You may obtain a copy of the License at
6e0dac50fSopenharmony_ci *
7e0dac50fSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8e0dac50fSopenharmony_ci *
9e0dac50fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10e0dac50fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11e0dac50fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12e0dac50fSopenharmony_ci * See the License for the specific language governing permissions and
13e0dac50fSopenharmony_ci * limitations under the License.
14e0dac50fSopenharmony_ci */
15e0dac50fSopenharmony_ci
16e0dac50fSopenharmony_ci#include "abstract_screen_controller.h"
17e0dac50fSopenharmony_ci
18e0dac50fSopenharmony_ci#include <sstream>
19e0dac50fSopenharmony_ci
20e0dac50fSopenharmony_ci#include <cinttypes>
21e0dac50fSopenharmony_ci#include <hitrace_meter.h>
22e0dac50fSopenharmony_ci#include <parameters.h>
23e0dac50fSopenharmony_ci#include <screen_manager/rs_screen_mode_info.h>
24e0dac50fSopenharmony_ci#include <screen_manager/screen_types.h>
25e0dac50fSopenharmony_ci#include <surface.h>
26e0dac50fSopenharmony_ci#include <thread>
27e0dac50fSopenharmony_ci
28e0dac50fSopenharmony_ci#include "sys_cap_util.h"
29e0dac50fSopenharmony_ci#include "display_manager_agent_controller.h"
30e0dac50fSopenharmony_ci#include "display_manager_service.h"
31e0dac50fSopenharmony_ci#include "event_runner.h"
32e0dac50fSopenharmony_ci#include "screen_rotation_controller.h"
33e0dac50fSopenharmony_ci#include "window_manager_hilog.h"
34e0dac50fSopenharmony_ci
35e0dac50fSopenharmony_ci#ifdef SOC_PERF_ENABLE
36e0dac50fSopenharmony_ci#include "socperf_client.h"
37e0dac50fSopenharmony_ci#endif
38e0dac50fSopenharmony_ci
39e0dac50fSopenharmony_cinamespace OHOS::Rosen {
40e0dac50fSopenharmony_cinamespace {
41e0dac50fSopenharmony_ciconstexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "AbstractScreenController"};
42e0dac50fSopenharmony_ciconst std::string CONTROLLER_THREAD_ID = "AbstractScreenControllerThread";
43e0dac50fSopenharmony_ciconst static uint32_t MAX_RETRY_NUM = 3;
44e0dac50fSopenharmony_ciconst static uint32_t RETRY_WAIT_MS = 100;
45e0dac50fSopenharmony_ci}
46e0dac50fSopenharmony_ci
47e0dac50fSopenharmony_ciAbstractScreenController::AbstractScreenController(std::recursive_mutex& mutex)
48e0dac50fSopenharmony_ci    : mutex_(mutex), rsInterface_(RSInterfaces::GetInstance())
49e0dac50fSopenharmony_ci{
50e0dac50fSopenharmony_ci    auto runner = AppExecFwk::EventRunner::Create(CONTROLLER_THREAD_ID);
51e0dac50fSopenharmony_ci    controllerHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner);
52e0dac50fSopenharmony_ci}
53e0dac50fSopenharmony_ci
54e0dac50fSopenharmony_ciAbstractScreenController::~AbstractScreenController() = default;
55e0dac50fSopenharmony_ci
56e0dac50fSopenharmony_civoid AbstractScreenController::Init()
57e0dac50fSopenharmony_ci{
58e0dac50fSopenharmony_ci    WLOGFI("screen controller init");
59e0dac50fSopenharmony_ci    RegisterRsScreenConnectionChangeListener();
60e0dac50fSopenharmony_ci}
61e0dac50fSopenharmony_ci
62e0dac50fSopenharmony_civoid AbstractScreenController::RegisterRsScreenConnectionChangeListener()
63e0dac50fSopenharmony_ci{
64e0dac50fSopenharmony_ci    WLOGFI("RegisterRsScreenConnectionChangeListener");
65e0dac50fSopenharmony_ci    auto res = rsInterface_.SetScreenChangeCallback(
66e0dac50fSopenharmony_ci        [this](ScreenId rsScreenId, ScreenEvent screenEvent) { OnRsScreenConnectionChange(rsScreenId, screenEvent); });
67e0dac50fSopenharmony_ci    if (res != StatusCode::SUCCESS) {
68e0dac50fSopenharmony_ci        auto task = [this] {
69e0dac50fSopenharmony_ci            RegisterRsScreenConnectionChangeListener();
70e0dac50fSopenharmony_ci        };
71e0dac50fSopenharmony_ci        // post task after 50 ms.
72e0dac50fSopenharmony_ci        controllerHandler_->PostTask(task, "wms:RegisterRsScreenConnectionChangeListener",
73e0dac50fSopenharmony_ci            50, AppExecFwk::EventQueue::Priority::HIGH);
74e0dac50fSopenharmony_ci    }
75e0dac50fSopenharmony_ci}
76e0dac50fSopenharmony_ci
77e0dac50fSopenharmony_cistd::vector<ScreenId> AbstractScreenController::GetAllScreenIds() const
78e0dac50fSopenharmony_ci{
79e0dac50fSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(mutex_);
80e0dac50fSopenharmony_ci    std::vector<ScreenId> res;
81e0dac50fSopenharmony_ci    for (const auto& iter : dmsScreenMap_) {
82e0dac50fSopenharmony_ci        res.emplace_back(iter.first);
83e0dac50fSopenharmony_ci    }
84e0dac50fSopenharmony_ci    return res;
85e0dac50fSopenharmony_ci}
86e0dac50fSopenharmony_ci
87e0dac50fSopenharmony_cistd::vector<ScreenId> AbstractScreenController::GetAllValidScreenIds(const std::vector<ScreenId>& screenIds) const
88e0dac50fSopenharmony_ci{
89e0dac50fSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(mutex_);
90e0dac50fSopenharmony_ci    std::vector<ScreenId> validScreenIds;
91e0dac50fSopenharmony_ci    for (ScreenId screenId : screenIds) {
92e0dac50fSopenharmony_ci        auto screenIdIter = std::find(validScreenIds.begin(), validScreenIds.end(), screenId);
93e0dac50fSopenharmony_ci        if (screenIdIter != validScreenIds.end()) {
94e0dac50fSopenharmony_ci            continue;
95e0dac50fSopenharmony_ci        }
96e0dac50fSopenharmony_ci        auto iter = dmsScreenMap_.find(screenId);
97e0dac50fSopenharmony_ci        if (iter != dmsScreenMap_.end() && iter->second->type_ != ScreenType::UNDEFINED) {
98e0dac50fSopenharmony_ci            validScreenIds.emplace_back(screenId);
99e0dac50fSopenharmony_ci        }
100e0dac50fSopenharmony_ci    }
101e0dac50fSopenharmony_ci    return validScreenIds;
102e0dac50fSopenharmony_ci}
103e0dac50fSopenharmony_ci
104e0dac50fSopenharmony_ciconst std::shared_ptr<RSDisplayNode>& AbstractScreenController::GetRSDisplayNodeByScreenId(ScreenId dmsScreenId) const
105e0dac50fSopenharmony_ci{
106e0dac50fSopenharmony_ci    static std::shared_ptr<RSDisplayNode> notFound = nullptr;
107e0dac50fSopenharmony_ci    sptr<AbstractScreen> screen = GetAbstractScreen(dmsScreenId);
108e0dac50fSopenharmony_ci    if (screen == nullptr) {
109e0dac50fSopenharmony_ci        WLOGFE("screen is nullptr");
110e0dac50fSopenharmony_ci        return notFound;
111e0dac50fSopenharmony_ci    }
112e0dac50fSopenharmony_ci    if (screen->rsDisplayNode_ == nullptr) {
113e0dac50fSopenharmony_ci        WLOGE("rsDisplayNode_ is nullptr");
114e0dac50fSopenharmony_ci        return notFound;
115e0dac50fSopenharmony_ci    }
116e0dac50fSopenharmony_ci    WLOGI("GetRSDisplayNodeByScreenId: screen: %{public}" PRIu64", nodeId: %{public}" PRIu64" ",
117e0dac50fSopenharmony_ci        screen->dmsId_, screen->rsDisplayNode_->GetId());
118e0dac50fSopenharmony_ci    return screen->rsDisplayNode_;
119e0dac50fSopenharmony_ci}
120e0dac50fSopenharmony_ci
121e0dac50fSopenharmony_civoid AbstractScreenController::UpdateRSTree(ScreenId dmsScreenId, ScreenId parentScreenId,
122e0dac50fSopenharmony_ci    std::shared_ptr<RSSurfaceNode>& surfaceNode, bool isAdd, bool isMultiDisplay)
123e0dac50fSopenharmony_ci{
124e0dac50fSopenharmony_ci    sptr<AbstractScreen> abstractScreen = GetAbstractScreen(dmsScreenId);
125e0dac50fSopenharmony_ci    if (abstractScreen == nullptr) {
126e0dac50fSopenharmony_ci        WLOGE("[UpdateRSTree] can not find abstractScreen");
127e0dac50fSopenharmony_ci        return;
128e0dac50fSopenharmony_ci    }
129e0dac50fSopenharmony_ci    if (isMultiDisplay) {
130e0dac50fSopenharmony_ci        sptr<AbstractScreen> parentAbstractScreen = GetAbstractScreen(parentScreenId);
131e0dac50fSopenharmony_ci        if (parentAbstractScreen == nullptr) {
132e0dac50fSopenharmony_ci            WLOGE("[UpdateRSTree] can not find parentAbstractScreen");
133e0dac50fSopenharmony_ci            return;
134e0dac50fSopenharmony_ci        }
135e0dac50fSopenharmony_ci        if (parentAbstractScreen->rsDisplayNode_ == nullptr) {
136e0dac50fSopenharmony_ci            WLOGE("rsDisplayNode of parentAbstractScreen is nullptr");
137e0dac50fSopenharmony_ci            return;
138e0dac50fSopenharmony_ci        }
139e0dac50fSopenharmony_ci        abstractScreen->UpdateDisplayGroupRSTree(surfaceNode, parentAbstractScreen->rsDisplayNode_->GetId(), isAdd);
140e0dac50fSopenharmony_ci    } else {
141e0dac50fSopenharmony_ci        abstractScreen->UpdateRSTree(surfaceNode, isAdd);
142e0dac50fSopenharmony_ci    }
143e0dac50fSopenharmony_ci}
144e0dac50fSopenharmony_ci
145e0dac50fSopenharmony_ciDMError AbstractScreenController::AddSurfaceNodeToScreen(ScreenId dmsScreenId,
146e0dac50fSopenharmony_ci    std::shared_ptr<RSSurfaceNode>& surfaceNode, bool onTop)
147e0dac50fSopenharmony_ci{
148e0dac50fSopenharmony_ci    sptr<AbstractScreen> abstractScreen = GetAbstractScreen(dmsScreenId);
149e0dac50fSopenharmony_ci    if (abstractScreen == nullptr) {
150e0dac50fSopenharmony_ci        WLOGFE("Can not find abstractScreen");
151e0dac50fSopenharmony_ci        return DMError::DM_ERROR_NULLPTR;
152e0dac50fSopenharmony_ci    }
153e0dac50fSopenharmony_ci    return abstractScreen->AddSurfaceNode(surfaceNode, onTop);
154e0dac50fSopenharmony_ci}
155e0dac50fSopenharmony_ci
156e0dac50fSopenharmony_ciDMError AbstractScreenController::RemoveSurfaceNodeFromScreen(ScreenId dmsScreenId,
157e0dac50fSopenharmony_ci    std::shared_ptr<RSSurfaceNode>& surfaceNode)
158e0dac50fSopenharmony_ci{
159e0dac50fSopenharmony_ci    sptr<AbstractScreen> abstractScreen = GetAbstractScreen(dmsScreenId);
160e0dac50fSopenharmony_ci    if (abstractScreen == nullptr) {
161e0dac50fSopenharmony_ci        WLOGFE("Can not find abstractScreen");
162e0dac50fSopenharmony_ci        return DMError::DM_ERROR_NULLPTR;
163e0dac50fSopenharmony_ci    }
164e0dac50fSopenharmony_ci    return abstractScreen->RemoveSurfaceNode(surfaceNode);
165e0dac50fSopenharmony_ci}
166e0dac50fSopenharmony_ci
167e0dac50fSopenharmony_cisptr<AbstractScreen> AbstractScreenController::GetAbstractScreen(ScreenId dmsScreenId) const
168e0dac50fSopenharmony_ci{
169e0dac50fSopenharmony_ci    WLOGD("GetAbstractScreen: screenId: %{public}" PRIu64"", dmsScreenId);
170e0dac50fSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(mutex_);
171e0dac50fSopenharmony_ci    auto iter = dmsScreenMap_.find(dmsScreenId);
172e0dac50fSopenharmony_ci    if (iter == dmsScreenMap_.end()) {
173e0dac50fSopenharmony_ci        WLOGE("did not find screen:%{public}" PRIu64"", dmsScreenId);
174e0dac50fSopenharmony_ci        return nullptr;
175e0dac50fSopenharmony_ci    }
176e0dac50fSopenharmony_ci    return iter->second;
177e0dac50fSopenharmony_ci}
178e0dac50fSopenharmony_ci
179e0dac50fSopenharmony_cisptr<AbstractScreenGroup> AbstractScreenController::GetAbstractScreenGroup(ScreenId dmsScreenId)
180e0dac50fSopenharmony_ci{
181e0dac50fSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(mutex_);
182e0dac50fSopenharmony_ci    auto iter = dmsScreenGroupMap_.find(dmsScreenId);
183e0dac50fSopenharmony_ci    if (iter == dmsScreenGroupMap_.end()) {
184e0dac50fSopenharmony_ci        WLOGE("did not find screen:%{public}" PRIu64"", dmsScreenId);
185e0dac50fSopenharmony_ci        return nullptr;
186e0dac50fSopenharmony_ci    }
187e0dac50fSopenharmony_ci    return iter->second;
188e0dac50fSopenharmony_ci}
189e0dac50fSopenharmony_ci
190e0dac50fSopenharmony_ciScreenId AbstractScreenController::GetDefaultAbstractScreenId()
191e0dac50fSopenharmony_ci{
192e0dac50fSopenharmony_ci    if (defaultRsScreenId_ == SCREEN_ID_INVALID) {
193e0dac50fSopenharmony_ci        defaultRsScreenId_ = rsInterface_.GetDefaultScreenId();
194e0dac50fSopenharmony_ci    }
195e0dac50fSopenharmony_ci    if (defaultRsScreenId_ == SCREEN_ID_INVALID) {
196e0dac50fSopenharmony_ci        WLOGFW("GetDefaultAbstractScreenId, rsDefaultId is invalid.");
197e0dac50fSopenharmony_ci        return SCREEN_ID_INVALID;
198e0dac50fSopenharmony_ci    }
199e0dac50fSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(mutex_);
200e0dac50fSopenharmony_ci    ScreenId defaultDmsScreenId;
201e0dac50fSopenharmony_ci    if (screenIdManager_.ConvertToDmsScreenId(defaultRsScreenId_, defaultDmsScreenId)) {
202e0dac50fSopenharmony_ci        WLOGFD("GetDefaultAbstractScreenId, screen:%{public}" PRIu64"", defaultDmsScreenId);
203e0dac50fSopenharmony_ci        return defaultDmsScreenId;
204e0dac50fSopenharmony_ci    }
205e0dac50fSopenharmony_ci    WLOGFI("GetDefaultAbstractScreenId, default screen is null, try to get.");
206e0dac50fSopenharmony_ci    ProcessScreenConnected(defaultRsScreenId_);
207e0dac50fSopenharmony_ci    return screenIdManager_.ConvertToDmsScreenId(defaultRsScreenId_);
208e0dac50fSopenharmony_ci}
209e0dac50fSopenharmony_ci
210e0dac50fSopenharmony_ciScreenId AbstractScreenController::ConvertToRsScreenId(ScreenId dmsScreenId) const
211e0dac50fSopenharmony_ci{
212e0dac50fSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(mutex_);
213e0dac50fSopenharmony_ci    return screenIdManager_.ConvertToRsScreenId(dmsScreenId);
214e0dac50fSopenharmony_ci}
215e0dac50fSopenharmony_ci
216e0dac50fSopenharmony_ciScreenId AbstractScreenController::ConvertToDmsScreenId(ScreenId rsScreenId) const
217e0dac50fSopenharmony_ci{
218e0dac50fSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(mutex_);
219e0dac50fSopenharmony_ci    return screenIdManager_.ConvertToDmsScreenId(rsScreenId);
220e0dac50fSopenharmony_ci}
221e0dac50fSopenharmony_ci
222e0dac50fSopenharmony_civoid AbstractScreenController::RegisterAbstractScreenCallback(sptr<AbstractScreenCallback> cb)
223e0dac50fSopenharmony_ci{
224e0dac50fSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(mutex_);
225e0dac50fSopenharmony_ci    abstractScreenCallback_ = cb;
226e0dac50fSopenharmony_ci    if (abstractScreenCallback_ == nullptr) {
227e0dac50fSopenharmony_ci        return;
228e0dac50fSopenharmony_ci    }
229e0dac50fSopenharmony_ci    for (auto& iter : dmsScreenMap_) {
230e0dac50fSopenharmony_ci        if (iter.second != nullptr) {
231e0dac50fSopenharmony_ci            WLOGFI("dmsScreenId :%{public}" PRIu64"", iter.first);
232e0dac50fSopenharmony_ci            abstractScreenCallback_->onConnect_(iter.second);
233e0dac50fSopenharmony_ci        }
234e0dac50fSopenharmony_ci    }
235e0dac50fSopenharmony_ci}
236e0dac50fSopenharmony_ci
237e0dac50fSopenharmony_civoid AbstractScreenController::OnRsScreenConnectionChange(ScreenId rsScreenId, ScreenEvent screenEvent)
238e0dac50fSopenharmony_ci{
239e0dac50fSopenharmony_ci    WLOGFI("RS screen event. rsScreenId:%{public}" PRIu64", defaultRsScreenId_:%{public}" PRIu64", event:%{public}u",
240e0dac50fSopenharmony_ci        rsScreenId, static_cast<uint64_t>(defaultRsScreenId_), static_cast<uint32_t>(screenEvent));
241e0dac50fSopenharmony_ci    if (screenEvent == ScreenEvent::CONNECTED) {
242e0dac50fSopenharmony_ci        auto task = [this, rsScreenId] {
243e0dac50fSopenharmony_ci            ProcessScreenConnected(rsScreenId);
244e0dac50fSopenharmony_ci        };
245e0dac50fSopenharmony_ci        controllerHandler_->PostTask(task, "wms:OnRsScreenConnectionChange", 0, AppExecFwk::EventQueue::Priority::HIGH);
246e0dac50fSopenharmony_ci    } else if (screenEvent == ScreenEvent::DISCONNECTED) {
247e0dac50fSopenharmony_ci        auto task = [this, rsScreenId] {
248e0dac50fSopenharmony_ci            ProcessScreenDisconnected(rsScreenId);
249e0dac50fSopenharmony_ci        };
250e0dac50fSopenharmony_ci        controllerHandler_->PostTask(task, "wms:OnRsScreenConnectionChange", 0, AppExecFwk::EventQueue::Priority::HIGH);
251e0dac50fSopenharmony_ci    } else {
252e0dac50fSopenharmony_ci        WLOGE("unknown message:%{public}ud", static_cast<uint8_t>(screenEvent));
253e0dac50fSopenharmony_ci    }
254e0dac50fSopenharmony_ci}
255e0dac50fSopenharmony_ci
256e0dac50fSopenharmony_civoid AbstractScreenController::ProcessDefaultScreenReconnected(ScreenId rsScreenId)
257e0dac50fSopenharmony_ci{
258e0dac50fSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(mutex_);
259e0dac50fSopenharmony_ci    if (rsScreenId != defaultRsScreenId_ || defaultRsScreenId_ == SCREEN_ID_INVALID) {
260e0dac50fSopenharmony_ci        return;
261e0dac50fSopenharmony_ci    }
262e0dac50fSopenharmony_ci    ScreenId dmsScreenId;
263e0dac50fSopenharmony_ci    if (!screenIdManager_.ConvertToDmsScreenId(rsScreenId, dmsScreenId)) {
264e0dac50fSopenharmony_ci        WLOGFE("disconnect screen, rsScreenId=%{public}" PRIu64" is not in rs2DmsScreenIdMap_", rsScreenId);
265e0dac50fSopenharmony_ci        return;
266e0dac50fSopenharmony_ci    }
267e0dac50fSopenharmony_ci    WLOGFD("rsScreenId=%{public}" PRIu64", dmsScreenId=%{public}" PRIu64", "
268e0dac50fSopenharmony_ci        "defaultRsScreenId: %{public}" PRIu64"", rsScreenId, dmsScreenId, static_cast<uint64_t>(defaultRsScreenId_));
269e0dac50fSopenharmony_ci    auto dmsScreenMapIter = dmsScreenMap_.find(dmsScreenId);
270e0dac50fSopenharmony_ci    if (dmsScreenMapIter != dmsScreenMap_.end()) {
271e0dac50fSopenharmony_ci        auto screen = dmsScreenMapIter->second;
272e0dac50fSopenharmony_ci        if (screen == nullptr) {
273e0dac50fSopenharmony_ci            WLOGFE("screen is nullptr");
274e0dac50fSopenharmony_ci            return;
275e0dac50fSopenharmony_ci        }
276e0dac50fSopenharmony_ci        auto groupDmsId = screen->lastGroupDmsId_;
277e0dac50fSopenharmony_ci        auto iter = dmsScreenGroupMap_.find(groupDmsId);
278e0dac50fSopenharmony_ci        if (iter == dmsScreenGroupMap_.end()) {
279e0dac50fSopenharmony_ci            WLOGFE("groupDmsId: %{public}" PRIu64"is not in dmsScreenGroupMap_.", groupDmsId);
280e0dac50fSopenharmony_ci            return;
281e0dac50fSopenharmony_ci        }
282e0dac50fSopenharmony_ci        sptr<AbstractScreenGroup> screenGroup = iter->second;
283e0dac50fSopenharmony_ci        if (screenGroup == nullptr) {
284e0dac50fSopenharmony_ci            WLOGFE("screenGroup is nullptr");
285e0dac50fSopenharmony_ci            return;
286e0dac50fSopenharmony_ci        }
287e0dac50fSopenharmony_ci        Point point;
288e0dac50fSopenharmony_ci        if (!screenGroup->AddChild(screen, point)) {
289e0dac50fSopenharmony_ci            WLOGE("fail to add screen to group. screen: %{public}" PRIu64"", screen->dmsId_);
290e0dac50fSopenharmony_ci            return;
291e0dac50fSopenharmony_ci        }
292e0dac50fSopenharmony_ci
293e0dac50fSopenharmony_ci        // Recover default screen, set power state again
294e0dac50fSopenharmony_ci        SetScreenPowerForAll(powerState_, PowerStateChangeReason::POWER_BUTTON, false);
295e0dac50fSopenharmony_ci        const uint32_t level = 165;
296e0dac50fSopenharmony_ci        RSInterfaces::GetInstance().SetScreenBacklight(rsScreenId, level);
297e0dac50fSopenharmony_ci    } else {
298e0dac50fSopenharmony_ci        WLOGFE("can't find screen in dmsScreenMap, dmsScreenId: %{public}" PRIu64"", dmsScreenId);
299e0dac50fSopenharmony_ci    }
300e0dac50fSopenharmony_ci}
301e0dac50fSopenharmony_ci
302e0dac50fSopenharmony_civoid AbstractScreenController::ProcessScreenConnected(ScreenId rsScreenId)
303e0dac50fSopenharmony_ci{
304e0dac50fSopenharmony_ci    WLOGFI("start");
305e0dac50fSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(mutex_);
306e0dac50fSopenharmony_ci    if (screenIdManager_.HasRsScreenId(rsScreenId)) {
307e0dac50fSopenharmony_ci        WLOGFD("reconnect screen, screenId=%{public}" PRIu64"", rsScreenId);
308e0dac50fSopenharmony_ci        ProcessDefaultScreenReconnected(rsScreenId);
309e0dac50fSopenharmony_ci        return;
310e0dac50fSopenharmony_ci    }
311e0dac50fSopenharmony_ci    auto absScreen = InitAndGetScreen(rsScreenId);
312e0dac50fSopenharmony_ci    if (absScreen == nullptr) {
313e0dac50fSopenharmony_ci        return;
314e0dac50fSopenharmony_ci    }
315e0dac50fSopenharmony_ci    sptr<AbstractScreenGroup> screenGroup = AddToGroupLocked(absScreen);
316e0dac50fSopenharmony_ci    if (screenGroup == nullptr) {
317e0dac50fSopenharmony_ci        return;
318e0dac50fSopenharmony_ci    }
319e0dac50fSopenharmony_ci    if (rsScreenId == rsInterface_.GetDefaultScreenId() && absScreen->rsDisplayNode_ != nullptr) {
320e0dac50fSopenharmony_ci        absScreen->screenRequestedOrientation_ = buildInDefaultOrientation_;
321e0dac50fSopenharmony_ci        Rotation rotationAfter = absScreen->CalcRotation(absScreen->screenRequestedOrientation_);
322e0dac50fSopenharmony_ci        WLOGFD("set default rotation to %{public}d for buildin screen", rotationAfter);
323e0dac50fSopenharmony_ci        sptr<SupportedScreenModes> abstractScreenModes = absScreen->GetActiveScreenMode();
324e0dac50fSopenharmony_ci        if (abstractScreenModes != nullptr) {
325e0dac50fSopenharmony_ci            float w = abstractScreenModes->width_;
326e0dac50fSopenharmony_ci            float h = abstractScreenModes->height_;
327e0dac50fSopenharmony_ci            float x = 0;
328e0dac50fSopenharmony_ci            float y = 0;
329e0dac50fSopenharmony_ci            if (!IsVertical(rotationAfter)) {
330e0dac50fSopenharmony_ci                std::swap(w, h);
331e0dac50fSopenharmony_ci                x = (h - w) / 2; // 2: used to calculate offset to center display node
332e0dac50fSopenharmony_ci                y = (w - h) / 2; // 2: used to calculate offset to center display node
333e0dac50fSopenharmony_ci            }
334e0dac50fSopenharmony_ci            // 90.f is base degree
335e0dac50fSopenharmony_ci            absScreen->rsDisplayNode_->SetRotation(-90.0f * static_cast<uint32_t>(rotationAfter));
336e0dac50fSopenharmony_ci            absScreen->rsDisplayNode_->SetFrame(x, y, w, h);
337e0dac50fSopenharmony_ci            absScreen->rsDisplayNode_->SetBounds(x, y, w, h);
338e0dac50fSopenharmony_ci            auto transactionProxy = RSTransactionProxy::GetInstance();
339e0dac50fSopenharmony_ci            if (transactionProxy != nullptr) {
340e0dac50fSopenharmony_ci                transactionProxy->FlushImplicitTransaction();
341e0dac50fSopenharmony_ci            }
342e0dac50fSopenharmony_ci            absScreen->rotation_ = rotationAfter;
343e0dac50fSopenharmony_ci            absScreen->SetOrientation(absScreen->screenRequestedOrientation_);
344e0dac50fSopenharmony_ci        }
345e0dac50fSopenharmony_ci    }
346e0dac50fSopenharmony_ci    NotifyScreenConnected(absScreen->ConvertToScreenInfo());
347e0dac50fSopenharmony_ci    NotifyScreenGroupChanged(absScreen->ConvertToScreenInfo(), ScreenGroupChangeEvent::ADD_TO_GROUP);
348e0dac50fSopenharmony_ci    if (abstractScreenCallback_ != nullptr) {
349e0dac50fSopenharmony_ci        abstractScreenCallback_->onConnect_(absScreen);
350e0dac50fSopenharmony_ci    }
351e0dac50fSopenharmony_ci}
352e0dac50fSopenharmony_ci
353e0dac50fSopenharmony_cisptr<AbstractScreen> AbstractScreenController::InitAndGetScreen(ScreenId rsScreenId)
354e0dac50fSopenharmony_ci{
355e0dac50fSopenharmony_ci    ScreenId dmsScreenId = screenIdManager_.CreateAndGetNewScreenId(rsScreenId);
356e0dac50fSopenharmony_ci    RSScreenCapability screenCapability = rsInterface_.GetScreenCapability(rsScreenId);
357e0dac50fSopenharmony_ci    WLOGFI("Screen name is %{public}s, phyWidth is %{public}u, phyHeight is %{public}u",
358e0dac50fSopenharmony_ci        screenCapability.GetName().c_str(), screenCapability.GetPhyWidth(), screenCapability.GetPhyHeight());
359e0dac50fSopenharmony_ci
360e0dac50fSopenharmony_ci    sptr<AbstractScreen> absScreen =
361e0dac50fSopenharmony_ci        new(std::nothrow) AbstractScreen(this, screenCapability.GetName(), dmsScreenId, rsScreenId);
362e0dac50fSopenharmony_ci    if (absScreen == nullptr) {
363e0dac50fSopenharmony_ci        WLOGFE("new AbstractScreen failed.");
364e0dac50fSopenharmony_ci        screenIdManager_.DeleteScreenId(dmsScreenId);
365e0dac50fSopenharmony_ci        return nullptr;
366e0dac50fSopenharmony_ci    }
367e0dac50fSopenharmony_ci    absScreen->SetPhyWidth(screenCapability.GetPhyWidth());
368e0dac50fSopenharmony_ci    absScreen->SetPhyHeight(screenCapability.GetPhyHeight());
369e0dac50fSopenharmony_ci
370e0dac50fSopenharmony_ci    if (!InitAbstractScreenModesInfo(absScreen)) {
371e0dac50fSopenharmony_ci        screenIdManager_.DeleteScreenId(dmsScreenId);
372e0dac50fSopenharmony_ci        WLOGFE("InitAndGetScreen failed.");
373e0dac50fSopenharmony_ci        return nullptr;
374e0dac50fSopenharmony_ci    }
375e0dac50fSopenharmony_ci    dmsScreenMap_.insert(std::make_pair(dmsScreenId, absScreen));
376e0dac50fSopenharmony_ci    return absScreen;
377e0dac50fSopenharmony_ci}
378e0dac50fSopenharmony_ci
379e0dac50fSopenharmony_civoid AbstractScreenController::ProcessScreenDisconnected(ScreenId rsScreenId)
380e0dac50fSopenharmony_ci{
381e0dac50fSopenharmony_ci    ScreenId dmsScreenId;
382e0dac50fSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(mutex_);
383e0dac50fSopenharmony_ci    if (!screenIdManager_.ConvertToDmsScreenId(rsScreenId, dmsScreenId)) {
384e0dac50fSopenharmony_ci        WLOGFE("disconnect screen, rsScreenId=%{public}" PRIu64" is not in rs2DmsScreenIdMap_", rsScreenId);
385e0dac50fSopenharmony_ci        return;
386e0dac50fSopenharmony_ci    }
387e0dac50fSopenharmony_ci    WLOGFI("disconnect screen, rsScreenId= %{public}" PRIu64", dmsScreenId= %{public}" PRIu64"",
388e0dac50fSopenharmony_ci        rsScreenId, dmsScreenId);
389e0dac50fSopenharmony_ci    auto dmsScreenMapIter = dmsScreenMap_.find(dmsScreenId);
390e0dac50fSopenharmony_ci    sptr<AbstractScreenGroup> screenGroup;
391e0dac50fSopenharmony_ci    if (dmsScreenMapIter != dmsScreenMap_.end()) {
392e0dac50fSopenharmony_ci        auto screen = dmsScreenMapIter->second;
393e0dac50fSopenharmony_ci        if (abstractScreenCallback_ != nullptr && CheckScreenInScreenGroup(screen)) {
394e0dac50fSopenharmony_ci            if (rsScreenId == defaultRsScreenId_ && defaultRsScreenId_ != SCREEN_ID_INVALID) {
395e0dac50fSopenharmony_ci                // Disconnect default screen
396e0dac50fSopenharmony_ci                RemoveDefaultScreenFromGroupLocked(screen);
397e0dac50fSopenharmony_ci                return;
398e0dac50fSopenharmony_ci            }
399e0dac50fSopenharmony_ci            abstractScreenCallback_->onDisconnect_(screen);
400e0dac50fSopenharmony_ci        }
401e0dac50fSopenharmony_ci        screenGroup = RemoveFromGroupLocked(screen);
402e0dac50fSopenharmony_ci        if (screenGroup != nullptr) {
403e0dac50fSopenharmony_ci            NotifyScreenGroupChanged(screen->ConvertToScreenInfo(), ScreenGroupChangeEvent::REMOVE_FROM_GROUP);
404e0dac50fSopenharmony_ci        }
405e0dac50fSopenharmony_ci        dmsScreenMap_.erase(dmsScreenMapIter);
406e0dac50fSopenharmony_ci        NotifyScreenDisconnected(dmsScreenId);
407e0dac50fSopenharmony_ci        if (screenGroup != nullptr && screenGroup->combination_ == ScreenCombination::SCREEN_MIRROR &&
408e0dac50fSopenharmony_ci            screen->dmsId_ == screenGroup->mirrorScreenId_ && screenGroup->GetChildCount() != 0) {
409e0dac50fSopenharmony_ci            auto defaultScreenId = GetDefaultAbstractScreenId();
410e0dac50fSopenharmony_ci            std::vector<ScreenId> screens;
411e0dac50fSopenharmony_ci            for (auto& screenItem : screenGroup->GetChildren()) {
412e0dac50fSopenharmony_ci                if (screenItem->dmsId_ != defaultScreenId) {
413e0dac50fSopenharmony_ci                    screens.emplace_back(screenItem->dmsId_);
414e0dac50fSopenharmony_ci                }
415e0dac50fSopenharmony_ci            }
416e0dac50fSopenharmony_ci            MakeMirror(defaultScreenId, screens);
417e0dac50fSopenharmony_ci        }
418e0dac50fSopenharmony_ci    }
419e0dac50fSopenharmony_ci    screenIdManager_.DeleteScreenId(dmsScreenId);
420e0dac50fSopenharmony_ci}
421e0dac50fSopenharmony_ci
422e0dac50fSopenharmony_cibool AbstractScreenController::InitAbstractScreenModesInfo(sptr<AbstractScreen>& absScreen)
423e0dac50fSopenharmony_ci{
424e0dac50fSopenharmony_ci    std::vector<RSScreenModeInfo> allModes = rsInterface_.GetScreenSupportedModes(absScreen->rsId_);
425e0dac50fSopenharmony_ci    if (allModes.size() == 0) {
426e0dac50fSopenharmony_ci        WLOGE("supported screen mode is 0, screenId=%{public}" PRIu64"", absScreen->rsId_);
427e0dac50fSopenharmony_ci        return false;
428e0dac50fSopenharmony_ci    }
429e0dac50fSopenharmony_ci    for (const RSScreenModeInfo& rsScreenModeInfo : allModes) {
430e0dac50fSopenharmony_ci        sptr<SupportedScreenModes> info = new(std::nothrow) SupportedScreenModes();
431e0dac50fSopenharmony_ci        if (info == nullptr) {
432e0dac50fSopenharmony_ci            WLOGFE("create SupportedScreenModes failed");
433e0dac50fSopenharmony_ci            return false;
434e0dac50fSopenharmony_ci        }
435e0dac50fSopenharmony_ci        info->id_ = static_cast<uint32_t>(rsScreenModeInfo.GetScreenModeId());
436e0dac50fSopenharmony_ci        info->width_ = static_cast<uint32_t>(rsScreenModeInfo.GetScreenWidth());
437e0dac50fSopenharmony_ci        info->height_ = static_cast<uint32_t>(rsScreenModeInfo.GetScreenHeight());
438e0dac50fSopenharmony_ci        info->refreshRate_ = rsScreenModeInfo.GetScreenRefreshRate();
439e0dac50fSopenharmony_ci        absScreen->modes_.push_back(info);
440e0dac50fSopenharmony_ci        WLOGD("fill screen idx:%{public}d w/h:%{public}d/%{public}d",
441e0dac50fSopenharmony_ci            rsScreenModeInfo.GetScreenModeId(), info->width_, info->height_);
442e0dac50fSopenharmony_ci    }
443e0dac50fSopenharmony_ci    int32_t activeModeId = rsInterface_.GetScreenActiveMode(absScreen->rsId_).GetScreenModeId();
444e0dac50fSopenharmony_ci    WLOGD("fill screen activeModeId:%{public}d", activeModeId);
445e0dac50fSopenharmony_ci    if (static_cast<std::size_t>(activeModeId) >= allModes.size()) {
446e0dac50fSopenharmony_ci        WLOGE("activeModeId exceed, screenId=%{public}" PRIu64", activeModeId:%{public}d/%{public}ud",
447e0dac50fSopenharmony_ci            absScreen->rsId_, activeModeId, static_cast<uint32_t>(allModes.size()));
448e0dac50fSopenharmony_ci        return false;
449e0dac50fSopenharmony_ci    }
450e0dac50fSopenharmony_ci    absScreen->activeIdx_ = activeModeId;
451e0dac50fSopenharmony_ci    return true;
452e0dac50fSopenharmony_ci}
453e0dac50fSopenharmony_ci
454e0dac50fSopenharmony_cisptr<AbstractScreenGroup> AbstractScreenController::AddToGroupLocked(sptr<AbstractScreen> newScreen)
455e0dac50fSopenharmony_ci{
456e0dac50fSopenharmony_ci    sptr<AbstractScreenGroup> res;
457e0dac50fSopenharmony_ci    if (dmsScreenGroupMap_.empty()) {
458e0dac50fSopenharmony_ci        WLOGFI("connect the first screen");
459e0dac50fSopenharmony_ci        res = AddAsFirstScreenLocked(newScreen);
460e0dac50fSopenharmony_ci    } else {
461e0dac50fSopenharmony_ci        res = AddAsSuccedentScreenLocked(newScreen);
462e0dac50fSopenharmony_ci    }
463e0dac50fSopenharmony_ci    return res;
464e0dac50fSopenharmony_ci}
465e0dac50fSopenharmony_ci
466e0dac50fSopenharmony_civoid AbstractScreenController::RemoveDefaultScreenFromGroupLocked(sptr<AbstractScreen> screen)
467e0dac50fSopenharmony_ci{
468e0dac50fSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(mutex_);
469e0dac50fSopenharmony_ci    if (screen == nullptr) {
470e0dac50fSopenharmony_ci        return;
471e0dac50fSopenharmony_ci    }
472e0dac50fSopenharmony_ci    auto groupDmsId = screen->groupDmsId_;
473e0dac50fSopenharmony_ci    auto iter = dmsScreenGroupMap_.find(groupDmsId);
474e0dac50fSopenharmony_ci    if (iter == dmsScreenGroupMap_.end()) {
475e0dac50fSopenharmony_ci        WLOGFE("groupDmsId:%{public}" PRIu64"is not in dmsScreenGroupMap_.", groupDmsId);
476e0dac50fSopenharmony_ci        return;
477e0dac50fSopenharmony_ci    }
478e0dac50fSopenharmony_ci    sptr<AbstractScreenGroup> screenGroup = iter->second;
479e0dac50fSopenharmony_ci    if (screenGroup == nullptr) {
480e0dac50fSopenharmony_ci        return;
481e0dac50fSopenharmony_ci    }
482e0dac50fSopenharmony_ci    auto rsScreenId = screen->rsId_;
483e0dac50fSopenharmony_ci    bool res = screenGroup->RemoveDefaultScreen(screen);
484e0dac50fSopenharmony_ci    if (!res) {
485e0dac50fSopenharmony_ci        WLOGFE("RemoveDefaultScreen failed, rsScreenId: %{public}" PRIu64"", rsScreenId);
486e0dac50fSopenharmony_ci    }
487e0dac50fSopenharmony_ci}
488e0dac50fSopenharmony_ci
489e0dac50fSopenharmony_cisptr<AbstractScreenGroup> AbstractScreenController::RemoveFromGroupLocked(sptr<AbstractScreen> screen)
490e0dac50fSopenharmony_ci{
491e0dac50fSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(mutex_);
492e0dac50fSopenharmony_ci    if (screen == nullptr) {
493e0dac50fSopenharmony_ci        return nullptr;
494e0dac50fSopenharmony_ci    }
495e0dac50fSopenharmony_ci    auto groupDmsId = screen->groupDmsId_;
496e0dac50fSopenharmony_ci    auto iter = dmsScreenGroupMap_.find(groupDmsId);
497e0dac50fSopenharmony_ci    if (iter == dmsScreenGroupMap_.end()) {
498e0dac50fSopenharmony_ci        WLOGFE("groupDmsId:%{public}" PRIu64"is not in dmsScreenGroupMap_.", groupDmsId);
499e0dac50fSopenharmony_ci        return nullptr;
500e0dac50fSopenharmony_ci    }
501e0dac50fSopenharmony_ci    sptr<AbstractScreenGroup> screenGroup = iter->second;
502e0dac50fSopenharmony_ci    if (!RemoveChildFromGroup(screen, screenGroup)) {
503e0dac50fSopenharmony_ci        WLOGFE("RemoveChildFromGroup failed");
504e0dac50fSopenharmony_ci        return nullptr;
505e0dac50fSopenharmony_ci    }
506e0dac50fSopenharmony_ci    return screenGroup;
507e0dac50fSopenharmony_ci}
508e0dac50fSopenharmony_ci
509e0dac50fSopenharmony_cibool AbstractScreenController::RemoveChildFromGroup(sptr<AbstractScreen> screen, sptr<AbstractScreenGroup> screenGroup)
510e0dac50fSopenharmony_ci{
511e0dac50fSopenharmony_ci    bool res = screenGroup->RemoveChild(screen);
512e0dac50fSopenharmony_ci    if (!res) {
513e0dac50fSopenharmony_ci        WLOGFE("remove screen:%{public}" PRIu64" failed from screenGroup:%{public}" PRIu64".",
514e0dac50fSopenharmony_ci              screen->dmsId_, screen->groupDmsId_);
515e0dac50fSopenharmony_ci        return false;
516e0dac50fSopenharmony_ci    }
517e0dac50fSopenharmony_ci    if (screenGroup->GetChildCount() == 0) {
518e0dac50fSopenharmony_ci        // Group removed, need to do something.
519e0dac50fSopenharmony_ci        std::lock_guard<std::recursive_mutex> lock(mutex_);
520e0dac50fSopenharmony_ci        dmsScreenGroupMap_.erase(screenGroup->dmsId_);
521e0dac50fSopenharmony_ci        dmsScreenMap_.erase(screenGroup->dmsId_);
522e0dac50fSopenharmony_ci    }
523e0dac50fSopenharmony_ci    return true;
524e0dac50fSopenharmony_ci}
525e0dac50fSopenharmony_ci
526e0dac50fSopenharmony_cibool AbstractScreenController::CheckScreenInScreenGroup(sptr<AbstractScreen> screen) const
527e0dac50fSopenharmony_ci{
528e0dac50fSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(mutex_);
529e0dac50fSopenharmony_ci    auto groupDmsId = screen->groupDmsId_;
530e0dac50fSopenharmony_ci    auto iter = dmsScreenGroupMap_.find(groupDmsId);
531e0dac50fSopenharmony_ci    if (iter == dmsScreenGroupMap_.end()) {
532e0dac50fSopenharmony_ci        WLOGFE("groupDmsId:%{public}" PRIu64"is not in dmsScreenGroupMap_.", groupDmsId);
533e0dac50fSopenharmony_ci        return false;
534e0dac50fSopenharmony_ci    }
535e0dac50fSopenharmony_ci    sptr<AbstractScreenGroup> screenGroup = iter->second;
536e0dac50fSopenharmony_ci    return screenGroup->HasChild(screen->dmsId_);
537e0dac50fSopenharmony_ci}
538e0dac50fSopenharmony_ci
539e0dac50fSopenharmony_cisptr<AbstractScreenGroup> AbstractScreenController::AddAsFirstScreenLocked(sptr<AbstractScreen> newScreen)
540e0dac50fSopenharmony_ci{
541e0dac50fSopenharmony_ci    ScreenId dmsGroupScreenId = screenIdManager_.CreateAndGetNewScreenId(SCREEN_ID_INVALID);
542e0dac50fSopenharmony_ci    std::ostringstream buffer;
543e0dac50fSopenharmony_ci    buffer<<"ScreenGroup_"<<dmsGroupScreenId;
544e0dac50fSopenharmony_ci    std::string name = buffer.str();
545e0dac50fSopenharmony_ci    // default ScreenCombination is mirror
546e0dac50fSopenharmony_ci    isExpandCombination_ = system::GetParameter("persist.display.expand.enabled", "0") == "1";
547e0dac50fSopenharmony_ci    sptr<AbstractScreenGroup> screenGroup;
548e0dac50fSopenharmony_ci    if (isExpandCombination_) {
549e0dac50fSopenharmony_ci        screenGroup = new(std::nothrow) AbstractScreenGroup(this, dmsGroupScreenId,
550e0dac50fSopenharmony_ci            SCREEN_ID_INVALID, name, ScreenCombination::SCREEN_EXPAND);
551e0dac50fSopenharmony_ci    } else {
552e0dac50fSopenharmony_ci        screenGroup = new(std::nothrow) AbstractScreenGroup(this, dmsGroupScreenId,
553e0dac50fSopenharmony_ci            SCREEN_ID_INVALID, name, ScreenCombination::SCREEN_MIRROR);
554e0dac50fSopenharmony_ci    }
555e0dac50fSopenharmony_ci
556e0dac50fSopenharmony_ci    if (screenGroup == nullptr) {
557e0dac50fSopenharmony_ci        WLOGE("new AbstractScreenGroup failed");
558e0dac50fSopenharmony_ci        screenIdManager_.DeleteScreenId(dmsGroupScreenId);
559e0dac50fSopenharmony_ci        return nullptr;
560e0dac50fSopenharmony_ci    }
561e0dac50fSopenharmony_ci    Point point;
562e0dac50fSopenharmony_ci    if (!screenGroup->AddChild(newScreen, point)) {
563e0dac50fSopenharmony_ci        WLOGE("fail to add screen to group. screen=%{public}" PRIu64"", newScreen->dmsId_);
564e0dac50fSopenharmony_ci        screenIdManager_.DeleteScreenId(dmsGroupScreenId);
565e0dac50fSopenharmony_ci        return nullptr;
566e0dac50fSopenharmony_ci    }
567e0dac50fSopenharmony_ci    auto iter = dmsScreenGroupMap_.find(dmsGroupScreenId);
568e0dac50fSopenharmony_ci    if (iter != dmsScreenGroupMap_.end()) {
569e0dac50fSopenharmony_ci        WLOGE("group screen existed. id=%{public}" PRIu64"", dmsGroupScreenId);
570e0dac50fSopenharmony_ci        dmsScreenGroupMap_.erase(iter);
571e0dac50fSopenharmony_ci    }
572e0dac50fSopenharmony_ci    dmsScreenGroupMap_.insert(std::make_pair(dmsGroupScreenId, screenGroup));
573e0dac50fSopenharmony_ci    dmsScreenMap_.insert(std::make_pair(dmsGroupScreenId, screenGroup));
574e0dac50fSopenharmony_ci    screenGroup->mirrorScreenId_ = newScreen->dmsId_;
575e0dac50fSopenharmony_ci    WLOGI("connect new group screen, screenId: %{public}" PRIu64", screenGroupId: %{public}" PRIu64", "
576e0dac50fSopenharmony_ci        "combination:%{public}u", newScreen->dmsId_, dmsGroupScreenId, newScreen->type_);
577e0dac50fSopenharmony_ci    return screenGroup;
578e0dac50fSopenharmony_ci}
579e0dac50fSopenharmony_ci
580e0dac50fSopenharmony_cisptr<AbstractScreenGroup> AbstractScreenController::AddAsSuccedentScreenLocked(sptr<AbstractScreen> newScreen)
581e0dac50fSopenharmony_ci{
582e0dac50fSopenharmony_ci    ScreenId defaultScreenId = GetDefaultAbstractScreenId();
583e0dac50fSopenharmony_ci    auto iter = dmsScreenMap_.find(defaultScreenId);
584e0dac50fSopenharmony_ci    if (iter == dmsScreenMap_.end()) {
585e0dac50fSopenharmony_ci        WLOGE("AddAsSuccedentScreenLocked. defaultScreenId:%{public}" PRIu64" is not in dmsScreenMap_.",
586e0dac50fSopenharmony_ci            defaultScreenId);
587e0dac50fSopenharmony_ci        return nullptr;
588e0dac50fSopenharmony_ci    }
589e0dac50fSopenharmony_ci    auto screen = iter->second;
590e0dac50fSopenharmony_ci    auto screenGroupIter = dmsScreenGroupMap_.find(screen->groupDmsId_);
591e0dac50fSopenharmony_ci    if (screenGroupIter == dmsScreenGroupMap_.end()) {
592e0dac50fSopenharmony_ci        WLOGE("AddAsSuccedentScreenLocked. groupDmsId:%{public}" PRIu64" is not in dmsScreenGroupMap_.",
593e0dac50fSopenharmony_ci            screen->groupDmsId_);
594e0dac50fSopenharmony_ci        return nullptr;
595e0dac50fSopenharmony_ci    }
596e0dac50fSopenharmony_ci    auto screenGroup = screenGroupIter->second;
597e0dac50fSopenharmony_ci    Point point;
598e0dac50fSopenharmony_ci    if (screenGroup->combination_ == ScreenCombination::SCREEN_EXPAND) {
599e0dac50fSopenharmony_ci        for (auto& child : screenGroup->GetChildren()) {
600e0dac50fSopenharmony_ci            WLOGD("AddAsSuccedentScreenLocked. defaultScreen rotation:%d", child->rotation_);
601e0dac50fSopenharmony_ci            if (child->rotation_ == Rotation::ROTATION_90 || child->rotation_ == Rotation::ROTATION_270) {
602e0dac50fSopenharmony_ci                point.posX_ += static_cast<int32_t>(child->GetActiveScreenMode()->height_);
603e0dac50fSopenharmony_ci            } else {
604e0dac50fSopenharmony_ci                point.posX_ += static_cast<int32_t>(child->GetActiveScreenMode()->width_);
605e0dac50fSopenharmony_ci            }
606e0dac50fSopenharmony_ci        }
607e0dac50fSopenharmony_ci        WLOGD("AddAsSuccedentScreenLocked. point:[%d %d]", point.posX_, point.posY_);
608e0dac50fSopenharmony_ci    }
609e0dac50fSopenharmony_ci    screenGroup->AddChild(newScreen, point);
610e0dac50fSopenharmony_ci    return screenGroup;
611e0dac50fSopenharmony_ci}
612e0dac50fSopenharmony_ci
613e0dac50fSopenharmony_ciScreenId AbstractScreenController::CreateVirtualScreen(VirtualScreenOption option,
614e0dac50fSopenharmony_ci    const sptr<IRemoteObject>& displayManagerAgent)
615e0dac50fSopenharmony_ci{
616e0dac50fSopenharmony_ci    ScreenId rsId = rsInterface_.CreateVirtualScreen(option.name_, option.width_,
617e0dac50fSopenharmony_ci        option.height_, option.surface_, SCREEN_ID_INVALID, option.flags_);
618e0dac50fSopenharmony_ci    WLOGFI("id: %{public}" PRIu64"", rsId);
619e0dac50fSopenharmony_ci    if (rsId == SCREEN_ID_INVALID) {
620e0dac50fSopenharmony_ci        return SCREEN_ID_INVALID;
621e0dac50fSopenharmony_ci    }
622e0dac50fSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(mutex_);
623e0dac50fSopenharmony_ci    ScreenId dmsScreenId = SCREEN_ID_INVALID;
624e0dac50fSopenharmony_ci    if (!screenIdManager_.ConvertToDmsScreenId(rsId, dmsScreenId)) {
625e0dac50fSopenharmony_ci        dmsScreenId = screenIdManager_.CreateAndGetNewScreenId(rsId);
626e0dac50fSopenharmony_ci        auto absScreen = InitVirtualScreen(dmsScreenId, rsId, option);
627e0dac50fSopenharmony_ci        if (absScreen == nullptr) {
628e0dac50fSopenharmony_ci            screenIdManager_.DeleteScreenId(dmsScreenId);
629e0dac50fSopenharmony_ci            return SCREEN_ID_INVALID;
630e0dac50fSopenharmony_ci        }
631e0dac50fSopenharmony_ci        dmsScreenMap_.insert(std::make_pair(dmsScreenId, absScreen));
632e0dac50fSopenharmony_ci        NotifyScreenConnected(absScreen->ConvertToScreenInfo());
633e0dac50fSopenharmony_ci        if (deathRecipient_ == nullptr) {
634e0dac50fSopenharmony_ci            deathRecipient_ =
635e0dac50fSopenharmony_ci                new AgentDeathRecipient([this](const sptr<IRemoteObject>& agent) { OnRemoteDied(agent); });
636e0dac50fSopenharmony_ci        }
637e0dac50fSopenharmony_ci        auto agIter = screenAgentMap_.find(displayManagerAgent);
638e0dac50fSopenharmony_ci        if (agIter == screenAgentMap_.end()) {
639e0dac50fSopenharmony_ci            displayManagerAgent->AddDeathRecipient(deathRecipient_);
640e0dac50fSopenharmony_ci        }
641e0dac50fSopenharmony_ci        screenAgentMap_[displayManagerAgent].emplace_back(dmsScreenId);
642e0dac50fSopenharmony_ci    } else {
643e0dac50fSopenharmony_ci        WLOGFI("id: %{public}" PRIu64" appears in screenIdManager_. ", rsId);
644e0dac50fSopenharmony_ci    }
645e0dac50fSopenharmony_ci    return dmsScreenId;
646e0dac50fSopenharmony_ci}
647e0dac50fSopenharmony_ci
648e0dac50fSopenharmony_cisptr<AbstractScreen> AbstractScreenController::InitVirtualScreen(ScreenId dmsScreenId, ScreenId rsId,
649e0dac50fSopenharmony_ci    VirtualScreenOption option)
650e0dac50fSopenharmony_ci{
651e0dac50fSopenharmony_ci    sptr<AbstractScreen> absScreen = new(std::nothrow) AbstractScreen(this, option.name_, dmsScreenId, rsId);
652e0dac50fSopenharmony_ci    sptr<SupportedScreenModes> info = new(std::nothrow) SupportedScreenModes();
653e0dac50fSopenharmony_ci    if (absScreen == nullptr || info == nullptr) {
654e0dac50fSopenharmony_ci        WLOGFI("new AbstractScreen or SupportedScreenModes failed");
655e0dac50fSopenharmony_ci        screenIdManager_.DeleteScreenId(dmsScreenId);
656e0dac50fSopenharmony_ci        rsInterface_.RemoveVirtualScreen(rsId);
657e0dac50fSopenharmony_ci        return nullptr;
658e0dac50fSopenharmony_ci    }
659e0dac50fSopenharmony_ci    info->width_ = option.width_;
660e0dac50fSopenharmony_ci    info->height_ = option.height_;
661e0dac50fSopenharmony_ci    auto defaultScreen = GetAbstractScreen(GetDefaultAbstractScreenId());
662e0dac50fSopenharmony_ci    if (defaultScreen != nullptr && defaultScreen->GetActiveScreenMode() != nullptr) {
663e0dac50fSopenharmony_ci        info->refreshRate_ = defaultScreen->GetActiveScreenMode()->refreshRate_;
664e0dac50fSopenharmony_ci    }
665e0dac50fSopenharmony_ci    absScreen->modes_.emplace_back(info);
666e0dac50fSopenharmony_ci    absScreen->activeIdx_ = 0;
667e0dac50fSopenharmony_ci    absScreen->type_ = ScreenType::VIRTUAL;
668e0dac50fSopenharmony_ci    absScreen->virtualPixelRatio_ = option.density_;
669e0dac50fSopenharmony_ci    return absScreen;
670e0dac50fSopenharmony_ci}
671e0dac50fSopenharmony_ci
672e0dac50fSopenharmony_ciDMError AbstractScreenController::DestroyVirtualScreen(ScreenId screenId)
673e0dac50fSopenharmony_ci{
674e0dac50fSopenharmony_ci    WLOGFI("AbstractScreenController::DestroyVirtualScreen");
675e0dac50fSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(mutex_);
676e0dac50fSopenharmony_ci    ScreenId rsScreenId = SCREEN_ID_INVALID;
677e0dac50fSopenharmony_ci    screenIdManager_.ConvertToRsScreenId(screenId, rsScreenId);
678e0dac50fSopenharmony_ci
679e0dac50fSopenharmony_ci    sptr<IDisplayManagerAgent> displayManagerAgent = nullptr;
680e0dac50fSopenharmony_ci    bool agentFound = false;
681e0dac50fSopenharmony_ci    for (auto &agentIter : screenAgentMap_) {
682e0dac50fSopenharmony_ci        for (auto iter = agentIter.second.begin(); iter != agentIter.second.end(); iter++) {
683e0dac50fSopenharmony_ci            if (*iter == screenId) {
684e0dac50fSopenharmony_ci                iter = agentIter.second.erase(iter);
685e0dac50fSopenharmony_ci                agentFound = true;
686e0dac50fSopenharmony_ci                break;
687e0dac50fSopenharmony_ci            }
688e0dac50fSopenharmony_ci        }
689e0dac50fSopenharmony_ci        if (agentFound) {
690e0dac50fSopenharmony_ci            if (agentIter.first != nullptr && agentIter.second.empty()) {
691e0dac50fSopenharmony_ci                agentIter.first->RemoveDeathRecipient(deathRecipient_);
692e0dac50fSopenharmony_ci                screenAgentMap_.erase(agentIter.first);
693e0dac50fSopenharmony_ci            }
694e0dac50fSopenharmony_ci            break;
695e0dac50fSopenharmony_ci        }
696e0dac50fSopenharmony_ci    }
697e0dac50fSopenharmony_ci
698e0dac50fSopenharmony_ci    if (rsScreenId != SCREEN_ID_INVALID && GetAbstractScreen(screenId) != nullptr) {
699e0dac50fSopenharmony_ci        ProcessScreenDisconnected(rsScreenId);
700e0dac50fSopenharmony_ci    }
701e0dac50fSopenharmony_ci    screenIdManager_.DeleteScreenId(screenId);
702e0dac50fSopenharmony_ci
703e0dac50fSopenharmony_ci    if (rsScreenId == SCREEN_ID_INVALID) {
704e0dac50fSopenharmony_ci        WLOGFE("DestroyVirtualScreen: No corresponding rsScreenId");
705e0dac50fSopenharmony_ci        return DMError::DM_ERROR_INVALID_PARAM;
706e0dac50fSopenharmony_ci    }
707e0dac50fSopenharmony_ci    rsInterface_.RemoveVirtualScreen(rsScreenId);
708e0dac50fSopenharmony_ci    return DMError::DM_OK;
709e0dac50fSopenharmony_ci}
710e0dac50fSopenharmony_ci
711e0dac50fSopenharmony_ciDMError AbstractScreenController::SetVirtualScreenSurface(ScreenId screenId, sptr<Surface> surface)
712e0dac50fSopenharmony_ci{
713e0dac50fSopenharmony_ci    WLOGFI("begin");
714e0dac50fSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(mutex_);
715e0dac50fSopenharmony_ci    int32_t res = -1;
716e0dac50fSopenharmony_ci    ScreenId rsScreenId;
717e0dac50fSopenharmony_ci    if (screenIdManager_.ConvertToRsScreenId(screenId, rsScreenId)) {
718e0dac50fSopenharmony_ci        res = rsInterface_.SetVirtualScreenSurface(rsScreenId, surface);
719e0dac50fSopenharmony_ci    }
720e0dac50fSopenharmony_ci    if (res != 0) {
721e0dac50fSopenharmony_ci        WLOGE("SetVirtualScreenSurface failed in RenderService");
722e0dac50fSopenharmony_ci        return DMError::DM_ERROR_RENDER_SERVICE_FAILED;
723e0dac50fSopenharmony_ci    }
724e0dac50fSopenharmony_ci    return DMError::DM_OK;
725e0dac50fSopenharmony_ci}
726e0dac50fSopenharmony_ci
727e0dac50fSopenharmony_civoid AbstractScreenController::SetBuildInDefaultOrientation(Orientation orientation)
728e0dac50fSopenharmony_ci{
729e0dac50fSopenharmony_ci    if (orientation >= Orientation::BEGIN && orientation <= Orientation::END) {
730e0dac50fSopenharmony_ci        buildInDefaultOrientation_ = orientation;
731e0dac50fSopenharmony_ci    }
732e0dac50fSopenharmony_ci}
733e0dac50fSopenharmony_ci
734e0dac50fSopenharmony_ciDMError AbstractScreenController::SetOrientation(ScreenId screenId, Orientation newOrientation,
735e0dac50fSopenharmony_ci    bool isFromWindow, bool withAnimation)
736e0dac50fSopenharmony_ci{
737e0dac50fSopenharmony_ci    WLOGD("set orientation. screen %{public}" PRIu64" orientation %{public}u", screenId, newOrientation);
738e0dac50fSopenharmony_ci    auto screen = GetAbstractScreen(screenId);
739e0dac50fSopenharmony_ci    if (screen == nullptr) {
740e0dac50fSopenharmony_ci        WLOGFE("fail to set orientation, cannot find screen %{public}" PRIu64"", screenId);
741e0dac50fSopenharmony_ci        return DMError::DM_ERROR_NULLPTR;
742e0dac50fSopenharmony_ci    }
743e0dac50fSopenharmony_ci    if (screen->isScreenGroup_) {
744e0dac50fSopenharmony_ci        WLOGE("cannot set orientation to the combination. screen: %{public}" PRIu64"", screenId);
745e0dac50fSopenharmony_ci        return DMError::DM_ERROR_NULLPTR;
746e0dac50fSopenharmony_ci    }
747e0dac50fSopenharmony_ci    if (isFromWindow) {
748e0dac50fSopenharmony_ci        if (newOrientation == Orientation::UNSPECIFIED) {
749e0dac50fSopenharmony_ci            newOrientation = screen->screenRequestedOrientation_;
750e0dac50fSopenharmony_ci            withAnimation = true;
751e0dac50fSopenharmony_ci        }
752e0dac50fSopenharmony_ci    } else {
753e0dac50fSopenharmony_ci        screen->screenRequestedOrientation_ = newOrientation;
754e0dac50fSopenharmony_ci    }
755e0dac50fSopenharmony_ci    if (screen->orientation_ == newOrientation) {
756e0dac50fSopenharmony_ci        WLOGFD("skip setting orientation. screen %{public}" PRIu64" orientation %{public}u", screenId, newOrientation);
757e0dac50fSopenharmony_ci        return DMError::DM_OK;
758e0dac50fSopenharmony_ci    }
759e0dac50fSopenharmony_ci    if (isFromWindow) {
760e0dac50fSopenharmony_ci        ScreenRotationController::ProcessOrientationSwitch(newOrientation, withAnimation);
761e0dac50fSopenharmony_ci    } else {
762e0dac50fSopenharmony_ci        Rotation rotationAfter = screen->CalcRotation(newOrientation);
763e0dac50fSopenharmony_ci        SetRotation(screenId, rotationAfter, false);
764e0dac50fSopenharmony_ci        screen->rotation_ = rotationAfter;
765e0dac50fSopenharmony_ci    }
766e0dac50fSopenharmony_ci    if (!screen->SetOrientation(newOrientation)) {
767e0dac50fSopenharmony_ci        WLOGE("fail to set rotation, screen %{public}" PRIu64"", screenId);
768e0dac50fSopenharmony_ci        return DMError::DM_ERROR_NULLPTR;
769e0dac50fSopenharmony_ci    }
770e0dac50fSopenharmony_ci
771e0dac50fSopenharmony_ci    // Notify rotation event to ScreenManager
772e0dac50fSopenharmony_ci    NotifyScreenChanged(screen->ConvertToScreenInfo(), ScreenChangeEvent::UPDATE_ORIENTATION);
773e0dac50fSopenharmony_ci    // Notify rotation event to AbstractDisplayController
774e0dac50fSopenharmony_ci    if (abstractScreenCallback_ != nullptr) {
775e0dac50fSopenharmony_ci        if (!withAnimation) {
776e0dac50fSopenharmony_ci            abstractScreenCallback_->onChange_(screen, DisplayChangeEvent::UPDATE_ORIENTATION_FROM_WINDOW);
777e0dac50fSopenharmony_ci        } else {
778e0dac50fSopenharmony_ci            abstractScreenCallback_->onChange_(screen, DisplayChangeEvent::UPDATE_ORIENTATION);
779e0dac50fSopenharmony_ci        }
780e0dac50fSopenharmony_ci    }
781e0dac50fSopenharmony_ci
782e0dac50fSopenharmony_ci    auto screenGroup = screen->GetGroup();
783e0dac50fSopenharmony_ci    if (screenGroup) {
784e0dac50fSopenharmony_ci        UpdateScreenGroupLayout(screenGroup);
785e0dac50fSopenharmony_ci    }
786e0dac50fSopenharmony_ci
787e0dac50fSopenharmony_ci    return DMError::DM_OK;
788e0dac50fSopenharmony_ci}
789e0dac50fSopenharmony_ci
790e0dac50fSopenharmony_civoid AbstractScreenController::UpdateScreenGroupLayout(sptr<AbstractScreenGroup> screenGroup)
791e0dac50fSopenharmony_ci{
792e0dac50fSopenharmony_ci    if (screenGroup->combination_ != ScreenCombination::SCREEN_EXPAND) {
793e0dac50fSopenharmony_ci        return;
794e0dac50fSopenharmony_ci    }
795e0dac50fSopenharmony_ci
796e0dac50fSopenharmony_ci    auto screens = screenGroup->GetChildren();
797e0dac50fSopenharmony_ci    if (screens.size() <= 1) {
798e0dac50fSopenharmony_ci        return;
799e0dac50fSopenharmony_ci    }
800e0dac50fSopenharmony_ci
801e0dac50fSopenharmony_ci    // update display node's start point from left to right.
802e0dac50fSopenharmony_ci    std::sort(screens.begin(), screens.end(), [](const auto &a, const auto &b) {
803e0dac50fSopenharmony_ci        return a->startPoint_.posX_ < b->startPoint_.posX_;
804e0dac50fSopenharmony_ci    });
805e0dac50fSopenharmony_ci
806e0dac50fSopenharmony_ci    Point point;
807e0dac50fSopenharmony_ci    uint32_t width = 0;
808e0dac50fSopenharmony_ci    for (auto& screen : screens) {
809e0dac50fSopenharmony_ci        auto mode = screen->GetActiveScreenMode();
810e0dac50fSopenharmony_ci        if (!mode) {
811e0dac50fSopenharmony_ci            WLOGE("no active screen mode");
812e0dac50fSopenharmony_ci            continue;
813e0dac50fSopenharmony_ci        }
814e0dac50fSopenharmony_ci
815e0dac50fSopenharmony_ci        if (screen->startPoint_.posX_ != point.posX_) {
816e0dac50fSopenharmony_ci            screen->UpdateRSDisplayNode(point);
817e0dac50fSopenharmony_ci            if (abstractScreenCallback_ != nullptr) {
818e0dac50fSopenharmony_ci                abstractScreenCallback_->onChange_(screen, DisplayChangeEvent::DISPLAY_SIZE_CHANGED);
819e0dac50fSopenharmony_ci            }
820e0dac50fSopenharmony_ci        }
821e0dac50fSopenharmony_ci
822e0dac50fSopenharmony_ci        if (screen->rotation_ == Rotation::ROTATION_90 ||
823e0dac50fSopenharmony_ci            screen->rotation_ == Rotation::ROTATION_270) {
824e0dac50fSopenharmony_ci            width = mode->height_;
825e0dac50fSopenharmony_ci        } else {
826e0dac50fSopenharmony_ci            width = mode->width_;
827e0dac50fSopenharmony_ci        }
828e0dac50fSopenharmony_ci
829e0dac50fSopenharmony_ci        point.posX_ += static_cast<int32_t>(width);
830e0dac50fSopenharmony_ci    }
831e0dac50fSopenharmony_ci}
832e0dac50fSopenharmony_ci
833e0dac50fSopenharmony_civoid AbstractScreenController::SetScreenRotateAnimation(
834e0dac50fSopenharmony_ci    sptr<AbstractScreen>& screen, ScreenId screenId, Rotation rotationAfter, bool withAnimation)
835e0dac50fSopenharmony_ci{
836e0dac50fSopenharmony_ci    sptr<SupportedScreenModes> abstractScreenModes = screen->GetActiveScreenMode();
837e0dac50fSopenharmony_ci    struct ScreenRect srect = {0, 0, 0, 0};
838e0dac50fSopenharmony_ci    if (abstractScreenModes != nullptr) {
839e0dac50fSopenharmony_ci        srect.h = abstractScreenModes->height_;
840e0dac50fSopenharmony_ci        srect.w = abstractScreenModes->width_;
841e0dac50fSopenharmony_ci    }
842e0dac50fSopenharmony_ci    if (!IsVertical(rotationAfter)) {
843e0dac50fSopenharmony_ci        std::swap(srect.w, srect.h);
844e0dac50fSopenharmony_ci        srect.x = (srect.h - srect.w) / 2; // 2: used to calculate offset to center display node
845e0dac50fSopenharmony_ci        srect.y = (srect.w - srect.h) / 2; // 2: used to calculate offset to center display node
846e0dac50fSopenharmony_ci    }
847e0dac50fSopenharmony_ci    const std::shared_ptr<RSDisplayNode>& displayNode = GetRSDisplayNodeByScreenId(screenId);
848e0dac50fSopenharmony_ci    if (displayNode == nullptr) {
849e0dac50fSopenharmony_ci        return;
850e0dac50fSopenharmony_ci    }
851e0dac50fSopenharmony_ci    if (rotationAfter == Rotation::ROTATION_0 && screen->rotation_ == Rotation::ROTATION_270) {
852e0dac50fSopenharmony_ci        WLOGFD("[FixOrientation] display rotate with animation");
853e0dac50fSopenharmony_ci        // avoid animation 270, 240, 210 ... 30, 0, should play from 90->0
854e0dac50fSopenharmony_ci        displayNode->SetRotation(90.f);
855e0dac50fSopenharmony_ci    } else if (rotationAfter == Rotation::ROTATION_270 && screen->rotation_ == Rotation::ROTATION_0) {
856e0dac50fSopenharmony_ci        WLOGFD("[FixOrientation] display rotate with animation");
857e0dac50fSopenharmony_ci        // avoid animation 0, 30, 60 ... 270, should play from 360->270
858e0dac50fSopenharmony_ci        displayNode->SetRotation(-360.f);
859e0dac50fSopenharmony_ci    }
860e0dac50fSopenharmony_ci    if (withAnimation) {
861e0dac50fSopenharmony_ci        WLOGFD("[FixOrientation] display rotate with animation %{public}u", rotationAfter);
862e0dac50fSopenharmony_ci        std::weak_ptr<RSDisplayNode> weakNode = GetRSDisplayNodeByScreenId(screenId);
863e0dac50fSopenharmony_ci        static const RSAnimationTimingProtocol timingProtocol(600); // animation time
864e0dac50fSopenharmony_ci        // animation curve: cubic [0.2, 0.0, 0.2, 1.0]
865e0dac50fSopenharmony_ci        static const RSAnimationTimingCurve curve = RSAnimationTimingCurve::CreateCubicCurve(0.2, 0.0, 0.2, 1.0);
866e0dac50fSopenharmony_ci#ifdef SOC_PERF_ENABLE
867e0dac50fSopenharmony_ci        // Increase frequency to improve windowRotation perf
868e0dac50fSopenharmony_ci        // 10027 means "gesture" level that setting duration: 800, lit_cpu_min_freq: 1421000, mid_cpu_min_feq: 1882000
869e0dac50fSopenharmony_ci        OHOS::SOCPERF::SocPerfClient::GetInstance().PerfRequest(10027, "");
870e0dac50fSopenharmony_ci#endif
871e0dac50fSopenharmony_ci        RSNode::Animate(timingProtocol, curve, [weakNode, srect, rotationAfter, this]() {
872e0dac50fSopenharmony_ci            auto displayNode = weakNode.lock();
873e0dac50fSopenharmony_ci            if (displayNode == nullptr) {
874e0dac50fSopenharmony_ci                WLOGFE("error, cannot get DisplayNode");
875e0dac50fSopenharmony_ci                return;
876e0dac50fSopenharmony_ci            }
877e0dac50fSopenharmony_ci            SetDisplayNode(rotationAfter, displayNode, srect);
878e0dac50fSopenharmony_ci        }, []() {
879e0dac50fSopenharmony_ci#ifdef SOC_PERF_ENABLE
880e0dac50fSopenharmony_ci            // ClosePerf in finishCallBack
881e0dac50fSopenharmony_ci            OHOS::SOCPERF::SocPerfClient::GetInstance().PerfRequestEx(10027, false, "");
882e0dac50fSopenharmony_ci#endif
883e0dac50fSopenharmony_ci        });
884e0dac50fSopenharmony_ci    } else {
885e0dac50fSopenharmony_ci        WLOGFD("[FixOrientation] display rotate without animation %{public}u", rotationAfter);
886e0dac50fSopenharmony_ci        SetDisplayNode(rotationAfter, displayNode, srect);
887e0dac50fSopenharmony_ci    }
888e0dac50fSopenharmony_ci}
889e0dac50fSopenharmony_ci
890e0dac50fSopenharmony_civoid AbstractScreenController::SetDisplayNode(Rotation rotationAfter,
891e0dac50fSopenharmony_ci    const std::shared_ptr<RSDisplayNode>& displayNode, struct ScreenRect srect)
892e0dac50fSopenharmony_ci{
893e0dac50fSopenharmony_ci    displayNode->SetRotation(-90.f * static_cast<uint32_t>(rotationAfter)); // 90.f is base degree
894e0dac50fSopenharmony_ci    displayNode->SetFrame(srect.x, srect.y, srect.w, srect.h);
895e0dac50fSopenharmony_ci    displayNode->SetBounds(srect.x, srect.y, srect.w, srect.h);
896e0dac50fSopenharmony_ci}
897e0dac50fSopenharmony_ci
898e0dac50fSopenharmony_civoid AbstractScreenController::OpenRotationSyncTransaction()
899e0dac50fSopenharmony_ci{
900e0dac50fSopenharmony_ci     // Before open transaction, it must flush first.
901e0dac50fSopenharmony_ci    auto transactionProxy = RSTransactionProxy::GetInstance();
902e0dac50fSopenharmony_ci    if (!transactionProxy) {
903e0dac50fSopenharmony_ci        return;
904e0dac50fSopenharmony_ci    }
905e0dac50fSopenharmony_ci    transactionProxy->FlushImplicitTransaction();
906e0dac50fSopenharmony_ci    auto syncTransactionController = RSSyncTransactionController::GetInstance();
907e0dac50fSopenharmony_ci    if (syncTransactionController) {
908e0dac50fSopenharmony_ci        syncTransactionController->OpenSyncTransaction();
909e0dac50fSopenharmony_ci    }
910e0dac50fSopenharmony_ci}
911e0dac50fSopenharmony_ci
912e0dac50fSopenharmony_civoid AbstractScreenController::CloseRotationSyncTransaction()
913e0dac50fSopenharmony_ci{
914e0dac50fSopenharmony_ci    auto syncTransactionController = RSSyncTransactionController::GetInstance();
915e0dac50fSopenharmony_ci    if (syncTransactionController) {
916e0dac50fSopenharmony_ci        syncTransactionController->CloseSyncTransaction();
917e0dac50fSopenharmony_ci    }
918e0dac50fSopenharmony_ci}
919e0dac50fSopenharmony_ci
920e0dac50fSopenharmony_cibool AbstractScreenController::SetRotation(ScreenId screenId, Rotation rotationAfter,
921e0dac50fSopenharmony_ci    bool isFromWindow, bool withAnimation)
922e0dac50fSopenharmony_ci{
923e0dac50fSopenharmony_ci    WLOGFI("Enter SetRotation, screenId: %{public}" PRIu64 ", rotation: %{public}u, isFromWindow: %{public}u,"
924e0dac50fSopenharmony_ci        "animation: %{public}u", screenId, rotationAfter, isFromWindow, withAnimation);
925e0dac50fSopenharmony_ci    auto screen = GetAbstractScreen(screenId);
926e0dac50fSopenharmony_ci    if (screen == nullptr) {
927e0dac50fSopenharmony_ci        WLOGFE("SetRotation error, cannot get screen with screenId: %{public}" PRIu64, screenId);
928e0dac50fSopenharmony_ci        return false;
929e0dac50fSopenharmony_ci    }
930e0dac50fSopenharmony_ci    if (rotationAfter == screen->rotation_) {
931e0dac50fSopenharmony_ci        WLOGFD("rotation not changed. screen %{public}" PRIu64" rotation %{public}u", screenId, rotationAfter);
932e0dac50fSopenharmony_ci        return false;
933e0dac50fSopenharmony_ci    }
934e0dac50fSopenharmony_ci    WLOGFD("set orientation. rotation %{public}u", rotationAfter);
935e0dac50fSopenharmony_ci    OpenRotationSyncTransaction();
936e0dac50fSopenharmony_ci    SetScreenRotateAnimation(screen, screenId, rotationAfter, withAnimation);
937e0dac50fSopenharmony_ci    screen->rotation_ = rotationAfter;
938e0dac50fSopenharmony_ci    CloseRotationSyncTransaction();
939e0dac50fSopenharmony_ci
940e0dac50fSopenharmony_ci    NotifyScreenChanged(screen->ConvertToScreenInfo(), ScreenChangeEvent::UPDATE_ROTATION);
941e0dac50fSopenharmony_ci    // Notify rotation event to AbstractDisplayController
942e0dac50fSopenharmony_ci    if (abstractScreenCallback_ != nullptr) {
943e0dac50fSopenharmony_ci        if (!withAnimation) {
944e0dac50fSopenharmony_ci            abstractScreenCallback_->onChange_(screen, DisplayChangeEvent::UPDATE_ROTATION_FROM_WINDOW);
945e0dac50fSopenharmony_ci        } else {
946e0dac50fSopenharmony_ci            abstractScreenCallback_->onChange_(screen, DisplayChangeEvent::UPDATE_ROTATION);
947e0dac50fSopenharmony_ci        }
948e0dac50fSopenharmony_ci    }
949e0dac50fSopenharmony_ci    return true;
950e0dac50fSopenharmony_ci}
951e0dac50fSopenharmony_ci
952e0dac50fSopenharmony_ciDMError AbstractScreenController::GetScreenSupportedColorGamuts(ScreenId screenId,
953e0dac50fSopenharmony_ci    std::vector<ScreenColorGamut>& colorGamuts)
954e0dac50fSopenharmony_ci{
955e0dac50fSopenharmony_ci    sptr<AbstractScreen> screen = GetAbstractScreen(screenId);
956e0dac50fSopenharmony_ci    if (screen == nullptr) {
957e0dac50fSopenharmony_ci        return DMError::DM_ERROR_INVALID_PARAM;
958e0dac50fSopenharmony_ci    }
959e0dac50fSopenharmony_ci    return screen->GetScreenSupportedColorGamuts(colorGamuts);
960e0dac50fSopenharmony_ci}
961e0dac50fSopenharmony_ci
962e0dac50fSopenharmony_ciDMError AbstractScreenController::GetScreenColorGamut(ScreenId screenId, ScreenColorGamut& colorGamut)
963e0dac50fSopenharmony_ci{
964e0dac50fSopenharmony_ci    sptr<AbstractScreen> screen = GetAbstractScreen(screenId);
965e0dac50fSopenharmony_ci    if (screen == nullptr) {
966e0dac50fSopenharmony_ci        return DMError::DM_ERROR_INVALID_PARAM;
967e0dac50fSopenharmony_ci    }
968e0dac50fSopenharmony_ci    return screen->GetScreenColorGamut(colorGamut);
969e0dac50fSopenharmony_ci}
970e0dac50fSopenharmony_ci
971e0dac50fSopenharmony_ciDMError AbstractScreenController::SetScreenColorGamut(ScreenId screenId, int32_t colorGamutIdx)
972e0dac50fSopenharmony_ci{
973e0dac50fSopenharmony_ci    sptr<AbstractScreen> screen = GetAbstractScreen(screenId);
974e0dac50fSopenharmony_ci    if (screen == nullptr) {
975e0dac50fSopenharmony_ci        return DMError::DM_ERROR_INVALID_PARAM;
976e0dac50fSopenharmony_ci    }
977e0dac50fSopenharmony_ci    return screen->SetScreenColorGamut(colorGamutIdx);
978e0dac50fSopenharmony_ci}
979e0dac50fSopenharmony_ci
980e0dac50fSopenharmony_ciDMError AbstractScreenController::GetScreenGamutMap(ScreenId screenId, ScreenGamutMap& gamutMap)
981e0dac50fSopenharmony_ci{
982e0dac50fSopenharmony_ci    sptr<AbstractScreen> screen = GetAbstractScreen(screenId);
983e0dac50fSopenharmony_ci    if (screen == nullptr) {
984e0dac50fSopenharmony_ci        return DMError::DM_ERROR_INVALID_PARAM;
985e0dac50fSopenharmony_ci    }
986e0dac50fSopenharmony_ci    return screen->GetScreenGamutMap(gamutMap);
987e0dac50fSopenharmony_ci}
988e0dac50fSopenharmony_ci
989e0dac50fSopenharmony_ciDMError AbstractScreenController::SetScreenGamutMap(ScreenId screenId, ScreenGamutMap gamutMap)
990e0dac50fSopenharmony_ci{
991e0dac50fSopenharmony_ci    sptr<AbstractScreen> screen = GetAbstractScreen(screenId);
992e0dac50fSopenharmony_ci    if (screen == nullptr) {
993e0dac50fSopenharmony_ci        return DMError::DM_ERROR_INVALID_PARAM;
994e0dac50fSopenharmony_ci    }
995e0dac50fSopenharmony_ci    return screen->SetScreenGamutMap(gamutMap);
996e0dac50fSopenharmony_ci}
997e0dac50fSopenharmony_ci
998e0dac50fSopenharmony_ciDMError AbstractScreenController::SetScreenColorTransform(ScreenId screenId)
999e0dac50fSopenharmony_ci{
1000e0dac50fSopenharmony_ci    sptr<AbstractScreen> screen = GetAbstractScreen(screenId);
1001e0dac50fSopenharmony_ci    if (screen == nullptr) {
1002e0dac50fSopenharmony_ci        return DMError::DM_ERROR_INVALID_PARAM;
1003e0dac50fSopenharmony_ci    }
1004e0dac50fSopenharmony_ci    return screen->SetScreenColorTransform();
1005e0dac50fSopenharmony_ci}
1006e0dac50fSopenharmony_ci
1007e0dac50fSopenharmony_ciDMError AbstractScreenController::SetScreenActiveMode(ScreenId screenId, uint32_t modeId)
1008e0dac50fSopenharmony_ci{
1009e0dac50fSopenharmony_ci    WLOGI("SetScreenActiveMode: RsScreenId: %{public}" PRIu64", modeId: %{public}u", screenId, modeId);
1010e0dac50fSopenharmony_ci    if (screenId == SCREEN_ID_INVALID) {
1011e0dac50fSopenharmony_ci        WLOGFE("SetScreenActiveMode: invalid screenId");
1012e0dac50fSopenharmony_ci        return DMError::DM_ERROR_NULLPTR;
1013e0dac50fSopenharmony_ci    }
1014e0dac50fSopenharmony_ci    uint32_t usedModeId = 0;
1015e0dac50fSopenharmony_ci    {
1016e0dac50fSopenharmony_ci        std::lock_guard<std::recursive_mutex> lock(mutex_);
1017e0dac50fSopenharmony_ci        auto screen = GetAbstractScreen(screenId);
1018e0dac50fSopenharmony_ci        if (screen == nullptr) {
1019e0dac50fSopenharmony_ci            WLOGFE("SetScreenActiveMode: Get AbstractScreen failed");
1020e0dac50fSopenharmony_ci            return DMError::DM_ERROR_NULLPTR;
1021e0dac50fSopenharmony_ci        }
1022e0dac50fSopenharmony_ci        ScreenId rsScreenId = SCREEN_ID_INVALID;
1023e0dac50fSopenharmony_ci        if (!screenIdManager_.ConvertToRsScreenId(screenId, rsScreenId)) {
1024e0dac50fSopenharmony_ci            WLOGFE("SetScreenActiveMode: No corresponding rsId");
1025e0dac50fSopenharmony_ci            return DMError::DM_ERROR_NULLPTR;
1026e0dac50fSopenharmony_ci        }
1027e0dac50fSopenharmony_ci        rsInterface_.SetScreenActiveMode(rsScreenId, modeId);
1028e0dac50fSopenharmony_ci        usedModeId = static_cast<uint32_t>(screen->activeIdx_);
1029e0dac50fSopenharmony_ci        screen->activeIdx_ = static_cast<int32_t>(modeId);
1030e0dac50fSopenharmony_ci    }
1031e0dac50fSopenharmony_ci    // add thread to process mode change sync event
1032e0dac50fSopenharmony_ci    if (usedModeId != modeId) {
1033e0dac50fSopenharmony_ci        WLOGI("SetScreenActiveMode: modeId: %{public}u ->  %{public}u", usedModeId, modeId);
1034e0dac50fSopenharmony_ci        auto func = [=]() {
1035e0dac50fSopenharmony_ci            ProcessScreenModeChanged(screenId);
1036e0dac50fSopenharmony_ci            return;
1037e0dac50fSopenharmony_ci        };
1038e0dac50fSopenharmony_ci        controllerHandler_->PostTask(func, "wms:ProcessScreenModeChanged", 0, AppExecFwk::EventQueue::Priority::HIGH);
1039e0dac50fSopenharmony_ci    }
1040e0dac50fSopenharmony_ci    return DMError::DM_OK;
1041e0dac50fSopenharmony_ci}
1042e0dac50fSopenharmony_ci
1043e0dac50fSopenharmony_civoid AbstractScreenController::ProcessScreenModeChanged(ScreenId dmsScreenId)
1044e0dac50fSopenharmony_ci{
1045e0dac50fSopenharmony_ci    sptr<AbstractScreen> absScreen = nullptr;
1046e0dac50fSopenharmony_ci    sptr<AbstractScreenCallback> absScreenCallback = nullptr;
1047e0dac50fSopenharmony_ci    sptr<SupportedScreenModes> activeScreenMode = nullptr;
1048e0dac50fSopenharmony_ci    {
1049e0dac50fSopenharmony_ci        std::lock_guard<std::recursive_mutex> lock(mutex_);
1050e0dac50fSopenharmony_ci        auto dmsScreenMapIter = dmsScreenMap_.find(dmsScreenId);
1051e0dac50fSopenharmony_ci        if (dmsScreenMapIter == dmsScreenMap_.end()) {
1052e0dac50fSopenharmony_ci            WLOGFE("dmsScreenId=%{public}" PRIu64" is not in dmsScreenMap", dmsScreenId);
1053e0dac50fSopenharmony_ci            return;
1054e0dac50fSopenharmony_ci        }
1055e0dac50fSopenharmony_ci        absScreen = GetAbstractScreen(dmsScreenId);
1056e0dac50fSopenharmony_ci        if (absScreen == nullptr) {
1057e0dac50fSopenharmony_ci            WLOGFE("screen is nullptr. dmsScreenId=%{public}" PRIu64"", dmsScreenId);
1058e0dac50fSopenharmony_ci            return;
1059e0dac50fSopenharmony_ci        }
1060e0dac50fSopenharmony_ci        activeScreenMode = absScreen->GetActiveScreenMode();
1061e0dac50fSopenharmony_ci        if (activeScreenMode == nullptr) {
1062e0dac50fSopenharmony_ci            WLOGFE("active screen mode is nullptr. dmsScreenId=%{public}" PRIu64"",
1063e0dac50fSopenharmony_ci                dmsScreenId);
1064e0dac50fSopenharmony_ci            return;
1065e0dac50fSopenharmony_ci        }
1066e0dac50fSopenharmony_ci        absScreenCallback = abstractScreenCallback_;
1067e0dac50fSopenharmony_ci    }
1068e0dac50fSopenharmony_ci    uint32_t width = activeScreenMode->width_;
1069e0dac50fSopenharmony_ci    uint32_t height = activeScreenMode->height_;
1070e0dac50fSopenharmony_ci    uint32_t refreshRate = activeScreenMode->refreshRate_;
1071e0dac50fSopenharmony_ci    HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:ProcessScreenModeChanged(%" PRIu64"),\
1072e0dac50fSopenharmony_ci        width*height(%u*%u), refreshRate(%u)", dmsScreenId, width, height, refreshRate);
1073e0dac50fSopenharmony_ci    if (absScreenCallback != nullptr) {
1074e0dac50fSopenharmony_ci        absScreenCallback->onChange_(absScreen, DisplayChangeEvent::DISPLAY_SIZE_CHANGED);
1075e0dac50fSopenharmony_ci    }
1076e0dac50fSopenharmony_ci    NotifyScreenChanged(absScreen->ConvertToScreenInfo(), ScreenChangeEvent::CHANGE_MODE);
1077e0dac50fSopenharmony_ci}
1078e0dac50fSopenharmony_ci
1079e0dac50fSopenharmony_ciDMError AbstractScreenController::MakeMirror(ScreenId screenId, std::vector<ScreenId> screens)
1080e0dac50fSopenharmony_ci{
1081e0dac50fSopenharmony_ci    WLOGI("MakeMirror, screenId:%{public}" PRIu64"", screenId);
1082e0dac50fSopenharmony_ci    sptr<AbstractScreen> screen = GetAbstractScreen(screenId);
1083e0dac50fSopenharmony_ci    if (screen == nullptr || screen->type_ != ScreenType::REAL) {
1084e0dac50fSopenharmony_ci        WLOGFE("screen is nullptr, or screenType is not real.");
1085e0dac50fSopenharmony_ci        return DMError::DM_ERROR_NULLPTR;
1086e0dac50fSopenharmony_ci    }
1087e0dac50fSopenharmony_ci    WLOGFD("GetAbstractScreenGroup start");
1088e0dac50fSopenharmony_ci    auto group = GetAbstractScreenGroup(screen->groupDmsId_);
1089e0dac50fSopenharmony_ci    if (group == nullptr) {
1090e0dac50fSopenharmony_ci        std::lock_guard<std::recursive_mutex> lock(mutex_);
1091e0dac50fSopenharmony_ci        group = AddToGroupLocked(screen);
1092e0dac50fSopenharmony_ci        if (group == nullptr) {
1093e0dac50fSopenharmony_ci            WLOGFE("group is nullptr");
1094e0dac50fSopenharmony_ci            return DMError::DM_ERROR_NULLPTR;
1095e0dac50fSopenharmony_ci        }
1096e0dac50fSopenharmony_ci        NotifyScreenGroupChanged(screen->ConvertToScreenInfo(), ScreenGroupChangeEvent::ADD_TO_GROUP);
1097e0dac50fSopenharmony_ci        if (group != nullptr && abstractScreenCallback_ != nullptr) {
1098e0dac50fSopenharmony_ci            abstractScreenCallback_->onConnect_(screen);
1099e0dac50fSopenharmony_ci        }
1100e0dac50fSopenharmony_ci    }
1101e0dac50fSopenharmony_ci    WLOGFD("GetAbstractScreenGroup end");
1102e0dac50fSopenharmony_ci    Point point;
1103e0dac50fSopenharmony_ci    std::vector<Point> startPoints;
1104e0dac50fSopenharmony_ci    startPoints.insert(startPoints.begin(), screens.size(), point);
1105e0dac50fSopenharmony_ci    bool filterMirroredScreen =
1106e0dac50fSopenharmony_ci        group->combination_ == ScreenCombination::SCREEN_MIRROR && group->mirrorScreenId_ == screen->dmsId_;
1107e0dac50fSopenharmony_ci    group->mirrorScreenId_ = screen->dmsId_;
1108e0dac50fSopenharmony_ci    ChangeScreenGroup(group, screens, startPoints, filterMirroredScreen, ScreenCombination::SCREEN_MIRROR);
1109e0dac50fSopenharmony_ci    WLOGFI("MakeMirror success");
1110e0dac50fSopenharmony_ci    return DMError::DM_OK;
1111e0dac50fSopenharmony_ci}
1112e0dac50fSopenharmony_ci
1113e0dac50fSopenharmony_ciDMError AbstractScreenController::StopScreens(const std::vector<ScreenId>& screenIds, ScreenCombination stopCombination)
1114e0dac50fSopenharmony_ci{
1115e0dac50fSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(mutex_);
1116e0dac50fSopenharmony_ci    for (ScreenId screenId : screenIds) {
1117e0dac50fSopenharmony_ci        WLOGFI("ScreenId: %{public}" PRIu64"", screenId);
1118e0dac50fSopenharmony_ci        auto screen = GetAbstractScreen(screenId);
1119e0dac50fSopenharmony_ci        if (screen == nullptr) {
1120e0dac50fSopenharmony_ci            WLOGFW("screen:%{public}" PRIu64" is nullptr", screenId);
1121e0dac50fSopenharmony_ci            continue;
1122e0dac50fSopenharmony_ci        }
1123e0dac50fSopenharmony_ci        auto iter = dmsScreenGroupMap_.find(screen->groupDmsId_);
1124e0dac50fSopenharmony_ci        if (iter == dmsScreenGroupMap_.end()) {
1125e0dac50fSopenharmony_ci            WLOGFW("groupDmsId:%{public}" PRIu64"is not in dmsScreenGroupMap_", screen->groupDmsId_);
1126e0dac50fSopenharmony_ci            continue;
1127e0dac50fSopenharmony_ci        }
1128e0dac50fSopenharmony_ci        sptr<AbstractScreenGroup> screenGroup = iter->second;
1129e0dac50fSopenharmony_ci        if (screenGroup == nullptr) {
1130e0dac50fSopenharmony_ci            WLOGFW("screenGroup:%{public}" PRIu64" is nullptr", screen->groupDmsId_);
1131e0dac50fSopenharmony_ci            continue;
1132e0dac50fSopenharmony_ci        }
1133e0dac50fSopenharmony_ci        if (screenGroup->combination_ != stopCombination) {
1134e0dac50fSopenharmony_ci            WLOGFW("try to stop screen in another combination");
1135e0dac50fSopenharmony_ci            continue;
1136e0dac50fSopenharmony_ci        }
1137e0dac50fSopenharmony_ci        if (screenGroup->combination_ == ScreenCombination::SCREEN_MIRROR &&
1138e0dac50fSopenharmony_ci            screen->dmsId_ == screenGroup->mirrorScreenId_) {
1139e0dac50fSopenharmony_ci            WLOGFW("try to stop main mirror screen");
1140e0dac50fSopenharmony_ci            continue;
1141e0dac50fSopenharmony_ci        }
1142e0dac50fSopenharmony_ci
1143e0dac50fSopenharmony_ci        if (abstractScreenCallback_ != nullptr && CheckScreenInScreenGroup(screen)) {
1144e0dac50fSopenharmony_ci            abstractScreenCallback_->onDisconnect_(screen);
1145e0dac50fSopenharmony_ci        }
1146e0dac50fSopenharmony_ci        bool res = RemoveChildFromGroup(screen, screenGroup);
1147e0dac50fSopenharmony_ci        if (res) {
1148e0dac50fSopenharmony_ci            NotifyScreenGroupChanged(screen->ConvertToScreenInfo(), ScreenGroupChangeEvent::REMOVE_FROM_GROUP);
1149e0dac50fSopenharmony_ci        }
1150e0dac50fSopenharmony_ci    }
1151e0dac50fSopenharmony_ci    return DMError::DM_OK;
1152e0dac50fSopenharmony_ci}
1153e0dac50fSopenharmony_ci
1154e0dac50fSopenharmony_civoid AbstractScreenController::ChangeScreenGroup(sptr<AbstractScreenGroup> group, const std::vector<ScreenId>& screens,
1155e0dac50fSopenharmony_ci    const std::vector<Point>& startPoints, bool filterScreen, ScreenCombination combination)
1156e0dac50fSopenharmony_ci{
1157e0dac50fSopenharmony_ci    std::map<ScreenId, bool> removeChildResMap;
1158e0dac50fSopenharmony_ci    std::vector<ScreenId> addScreens;
1159e0dac50fSopenharmony_ci    std::vector<Point> addChildPos;
1160e0dac50fSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(mutex_);
1161e0dac50fSopenharmony_ci    for (uint64_t i = 0; i != screens.size(); i++) {
1162e0dac50fSopenharmony_ci        ScreenId screenId = screens[i];
1163e0dac50fSopenharmony_ci        WLOGFI("ScreenId: %{public}" PRIu64"", screenId);
1164e0dac50fSopenharmony_ci        auto screen = GetAbstractScreen(screenId);
1165e0dac50fSopenharmony_ci        if (screen == nullptr) {
1166e0dac50fSopenharmony_ci            WLOGFE("screen:%{public}" PRIu64" is nullptr", screenId);
1167e0dac50fSopenharmony_ci            continue;
1168e0dac50fSopenharmony_ci        }
1169e0dac50fSopenharmony_ci        WLOGFI("Screen->groupDmsId_: %{public}" PRIu64"", screen->groupDmsId_);
1170e0dac50fSopenharmony_ci        if (filterScreen && screen->groupDmsId_ == group->dmsId_ && group->HasChild(screen->dmsId_)) {
1171e0dac50fSopenharmony_ci            continue;
1172e0dac50fSopenharmony_ci        }
1173e0dac50fSopenharmony_ci        if (abstractScreenCallback_ != nullptr && CheckScreenInScreenGroup(screen)) {
1174e0dac50fSopenharmony_ci            abstractScreenCallback_->onDisconnect_(screen);
1175e0dac50fSopenharmony_ci        }
1176e0dac50fSopenharmony_ci        auto originGroup = RemoveFromGroupLocked(screen);
1177e0dac50fSopenharmony_ci        addChildPos.emplace_back(startPoints[i]);
1178e0dac50fSopenharmony_ci        removeChildResMap[screenId] = originGroup != nullptr;
1179e0dac50fSopenharmony_ci        addScreens.emplace_back(screenId);
1180e0dac50fSopenharmony_ci    }
1181e0dac50fSopenharmony_ci    group->combination_ = combination;
1182e0dac50fSopenharmony_ci    AddScreenToGroup(group, addScreens, addChildPos, removeChildResMap);
1183e0dac50fSopenharmony_ci}
1184e0dac50fSopenharmony_ci
1185e0dac50fSopenharmony_civoid AbstractScreenController::AddScreenToGroup(sptr<AbstractScreenGroup> group,
1186e0dac50fSopenharmony_ci    const std::vector<ScreenId>& addScreens, const std::vector<Point>& addChildPos,
1187e0dac50fSopenharmony_ci    std::map<ScreenId, bool>& removeChildResMap)
1188e0dac50fSopenharmony_ci{
1189e0dac50fSopenharmony_ci    std::vector<sptr<ScreenInfo>> addToGroup;
1190e0dac50fSopenharmony_ci    std::vector<sptr<ScreenInfo>> removeFromGroup;
1191e0dac50fSopenharmony_ci    std::vector<sptr<ScreenInfo>> changeGroup;
1192e0dac50fSopenharmony_ci    for (uint64_t i = 0; i != addScreens.size(); i++) {
1193e0dac50fSopenharmony_ci        ScreenId screenId = addScreens[i];
1194e0dac50fSopenharmony_ci        sptr<AbstractScreen> screen = GetAbstractScreen(screenId);
1195e0dac50fSopenharmony_ci        if (screen == nullptr) {
1196e0dac50fSopenharmony_ci            continue;
1197e0dac50fSopenharmony_ci        }
1198e0dac50fSopenharmony_ci        Point expandPoint = addChildPos[i];
1199e0dac50fSopenharmony_ci        WLOGFI("screenId: %{public}" PRIu64", Point: %{public}d, %{public}d",
1200e0dac50fSopenharmony_ci            screen->dmsId_, expandPoint.posX_, expandPoint.posY_);
1201e0dac50fSopenharmony_ci        bool addChildRes = group->AddChild(screen, expandPoint);
1202e0dac50fSopenharmony_ci        if (removeChildResMap[screenId] && addChildRes) {
1203e0dac50fSopenharmony_ci            changeGroup.emplace_back(screen->ConvertToScreenInfo());
1204e0dac50fSopenharmony_ci            WLOGFD("changeGroup");
1205e0dac50fSopenharmony_ci        } else if (removeChildResMap[screenId]) {
1206e0dac50fSopenharmony_ci            WLOGFD("removeChild");
1207e0dac50fSopenharmony_ci            removeFromGroup.emplace_back(screen->ConvertToScreenInfo());
1208e0dac50fSopenharmony_ci        } else if (addChildRes) {
1209e0dac50fSopenharmony_ci            WLOGFD("AddChild");
1210e0dac50fSopenharmony_ci            addToGroup.emplace_back(screen->ConvertToScreenInfo());
1211e0dac50fSopenharmony_ci        } else {
1212e0dac50fSopenharmony_ci            WLOGFD("default, AddChild failed");
1213e0dac50fSopenharmony_ci        }
1214e0dac50fSopenharmony_ci        if (abstractScreenCallback_ != nullptr) {
1215e0dac50fSopenharmony_ci            abstractScreenCallback_->onConnect_(screen);
1216e0dac50fSopenharmony_ci        }
1217e0dac50fSopenharmony_ci    }
1218e0dac50fSopenharmony_ci
1219e0dac50fSopenharmony_ci    NotifyScreenGroupChanged(removeFromGroup, ScreenGroupChangeEvent::REMOVE_FROM_GROUP);
1220e0dac50fSopenharmony_ci    NotifyScreenGroupChanged(changeGroup, ScreenGroupChangeEvent::CHANGE_GROUP);
1221e0dac50fSopenharmony_ci    NotifyScreenGroupChanged(addToGroup, ScreenGroupChangeEvent::ADD_TO_GROUP);
1222e0dac50fSopenharmony_ci}
1223e0dac50fSopenharmony_ci
1224e0dac50fSopenharmony_cibool AbstractScreenController::MakeExpand(std::vector<ScreenId> screenIds, std::vector<Point> startPoints)
1225e0dac50fSopenharmony_ci{
1226e0dac50fSopenharmony_ci    ScreenId defaultScreenId = GetDefaultAbstractScreenId();
1227e0dac50fSopenharmony_ci    WLOGI("MakeExpand, defaultScreenId:%{public}" PRIu64"", defaultScreenId);
1228e0dac50fSopenharmony_ci    auto defaultScreen = GetAbstractScreen(defaultScreenId);
1229e0dac50fSopenharmony_ci    if (defaultScreen == nullptr) {
1230e0dac50fSopenharmony_ci        return false;
1231e0dac50fSopenharmony_ci    }
1232e0dac50fSopenharmony_ci    auto group = GetAbstractScreenGroup(defaultScreen->groupDmsId_);
1233e0dac50fSopenharmony_ci    if (group == nullptr) {
1234e0dac50fSopenharmony_ci        return false;
1235e0dac50fSopenharmony_ci    }
1236e0dac50fSopenharmony_ci    bool filterExpandScreen = group->combination_ == ScreenCombination::SCREEN_EXPAND;
1237e0dac50fSopenharmony_ci    ChangeScreenGroup(group, screenIds, startPoints, filterExpandScreen, ScreenCombination::SCREEN_EXPAND);
1238e0dac50fSopenharmony_ci    WLOGFI("MakeExpand success");
1239e0dac50fSopenharmony_ci    return true;
1240e0dac50fSopenharmony_ci}
1241e0dac50fSopenharmony_ci
1242e0dac50fSopenharmony_civoid AbstractScreenController::RemoveVirtualScreenFromGroup(std::vector<ScreenId> screens)
1243e0dac50fSopenharmony_ci{
1244e0dac50fSopenharmony_ci    if (screens.empty()) {
1245e0dac50fSopenharmony_ci        return;
1246e0dac50fSopenharmony_ci    }
1247e0dac50fSopenharmony_ci    std::vector<sptr<ScreenInfo>> removeFromGroup;
1248e0dac50fSopenharmony_ci    for (ScreenId screenId : screens) {
1249e0dac50fSopenharmony_ci        auto screen = GetAbstractScreen(screenId);
1250e0dac50fSopenharmony_ci        if (screen == nullptr || screen->type_ != ScreenType::VIRTUAL) {
1251e0dac50fSopenharmony_ci            continue;
1252e0dac50fSopenharmony_ci        }
1253e0dac50fSopenharmony_ci        auto originGroup = GetAbstractScreenGroup(screen->groupDmsId_);
1254e0dac50fSopenharmony_ci        if (originGroup == nullptr) {
1255e0dac50fSopenharmony_ci            continue;
1256e0dac50fSopenharmony_ci        }
1257e0dac50fSopenharmony_ci        if (!originGroup->HasChild(screenId)) {
1258e0dac50fSopenharmony_ci            continue;
1259e0dac50fSopenharmony_ci        }
1260e0dac50fSopenharmony_ci        if (abstractScreenCallback_ != nullptr && CheckScreenInScreenGroup(screen)) {
1261e0dac50fSopenharmony_ci            abstractScreenCallback_->onDisconnect_(screen);
1262e0dac50fSopenharmony_ci        }
1263e0dac50fSopenharmony_ci        RemoveFromGroupLocked(screen);
1264e0dac50fSopenharmony_ci        removeFromGroup.emplace_back(screen->ConvertToScreenInfo());
1265e0dac50fSopenharmony_ci    }
1266e0dac50fSopenharmony_ci    NotifyScreenGroupChanged(removeFromGroup, ScreenGroupChangeEvent::REMOVE_FROM_GROUP);
1267e0dac50fSopenharmony_ci}
1268e0dac50fSopenharmony_ci
1269e0dac50fSopenharmony_cibool AbstractScreenController::OnRemoteDied(const sptr<IRemoteObject>& agent)
1270e0dac50fSopenharmony_ci{
1271e0dac50fSopenharmony_ci    if (agent == nullptr) {
1272e0dac50fSopenharmony_ci        return false;
1273e0dac50fSopenharmony_ci    }
1274e0dac50fSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(mutex_);
1275e0dac50fSopenharmony_ci    auto agentIter = screenAgentMap_.find(agent);
1276e0dac50fSopenharmony_ci    if (agentIter != screenAgentMap_.end()) {
1277e0dac50fSopenharmony_ci        while (screenAgentMap_[agent].size() > 0) {
1278e0dac50fSopenharmony_ci            auto diedId = screenAgentMap_[agent][0];
1279e0dac50fSopenharmony_ci            WLOGI("destroy screenId in OnRemoteDied: %{public}" PRIu64"", diedId);
1280e0dac50fSopenharmony_ci            DMError res = DestroyVirtualScreen(diedId);
1281e0dac50fSopenharmony_ci            if (res != DMError::DM_OK) {
1282e0dac50fSopenharmony_ci                WLOGE("destroy failed in OnRemoteDied: %{public}" PRIu64"", diedId);
1283e0dac50fSopenharmony_ci            }
1284e0dac50fSopenharmony_ci        }
1285e0dac50fSopenharmony_ci        screenAgentMap_.erase(agent);
1286e0dac50fSopenharmony_ci    }
1287e0dac50fSopenharmony_ci    return true;
1288e0dac50fSopenharmony_ci}
1289e0dac50fSopenharmony_ci
1290e0dac50fSopenharmony_ciScreenId AbstractScreenController::ScreenIdManager::CreateAndGetNewScreenId(ScreenId rsScreenId)
1291e0dac50fSopenharmony_ci{
1292e0dac50fSopenharmony_ci    ScreenId dmsScreenId = dmsScreenCount_++;
1293e0dac50fSopenharmony_ci    if (dms2RsScreenIdMap_.find(dmsScreenId) != dms2RsScreenIdMap_.end()) {
1294e0dac50fSopenharmony_ci        WLOGFW("dmsScreenId: %{public}" PRIu64" exit in dms2RsScreenIdMap_, warning.", dmsScreenId);
1295e0dac50fSopenharmony_ci    }
1296e0dac50fSopenharmony_ci    dms2RsScreenIdMap_[dmsScreenId] = rsScreenId;
1297e0dac50fSopenharmony_ci    if (rsScreenId == SCREEN_ID_INVALID) {
1298e0dac50fSopenharmony_ci        return dmsScreenId;
1299e0dac50fSopenharmony_ci    }
1300e0dac50fSopenharmony_ci    if (rs2DmsScreenIdMap_.find(rsScreenId) != rs2DmsScreenIdMap_.end()) {
1301e0dac50fSopenharmony_ci        WLOGFW("rsScreenId: %{public}" PRIu64" exit in rs2DmsScreenIdMap_, warning.", rsScreenId);
1302e0dac50fSopenharmony_ci    }
1303e0dac50fSopenharmony_ci    rs2DmsScreenIdMap_[rsScreenId] = dmsScreenId;
1304e0dac50fSopenharmony_ci    return dmsScreenId;
1305e0dac50fSopenharmony_ci}
1306e0dac50fSopenharmony_ci
1307e0dac50fSopenharmony_cibool AbstractScreenController::ScreenIdManager::DeleteScreenId(ScreenId dmsScreenId)
1308e0dac50fSopenharmony_ci{
1309e0dac50fSopenharmony_ci    auto iter = dms2RsScreenIdMap_.find(dmsScreenId);
1310e0dac50fSopenharmony_ci    if (iter == dms2RsScreenIdMap_.end()) {
1311e0dac50fSopenharmony_ci        return false;
1312e0dac50fSopenharmony_ci    }
1313e0dac50fSopenharmony_ci    ScreenId rsScreenId = iter->second;
1314e0dac50fSopenharmony_ci    dms2RsScreenIdMap_.erase(dmsScreenId);
1315e0dac50fSopenharmony_ci    rs2DmsScreenIdMap_.erase(rsScreenId);
1316e0dac50fSopenharmony_ci    return true;
1317e0dac50fSopenharmony_ci}
1318e0dac50fSopenharmony_ci
1319e0dac50fSopenharmony_cibool AbstractScreenController::ScreenIdManager::HasDmsScreenId(ScreenId dmsScreenId) const
1320e0dac50fSopenharmony_ci{
1321e0dac50fSopenharmony_ci    return dms2RsScreenIdMap_.find(dmsScreenId) != dms2RsScreenIdMap_.end();
1322e0dac50fSopenharmony_ci}
1323e0dac50fSopenharmony_ci
1324e0dac50fSopenharmony_cibool AbstractScreenController::ScreenIdManager::HasRsScreenId(ScreenId dmsScreenId) const
1325e0dac50fSopenharmony_ci{
1326e0dac50fSopenharmony_ci    return rs2DmsScreenIdMap_.find(dmsScreenId) != rs2DmsScreenIdMap_.end();
1327e0dac50fSopenharmony_ci}
1328e0dac50fSopenharmony_ci
1329e0dac50fSopenharmony_cibool AbstractScreenController::ScreenIdManager::ConvertToRsScreenId(ScreenId dmsScreenId, ScreenId& rsScreenId) const
1330e0dac50fSopenharmony_ci{
1331e0dac50fSopenharmony_ci    auto iter = dms2RsScreenIdMap_.find(dmsScreenId);
1332e0dac50fSopenharmony_ci    if (iter == dms2RsScreenIdMap_.end()) {
1333e0dac50fSopenharmony_ci        return false;
1334e0dac50fSopenharmony_ci    }
1335e0dac50fSopenharmony_ci    rsScreenId = iter->second;
1336e0dac50fSopenharmony_ci    return true;
1337e0dac50fSopenharmony_ci}
1338e0dac50fSopenharmony_ci
1339e0dac50fSopenharmony_ciScreenId AbstractScreenController::ScreenIdManager::ConvertToRsScreenId(ScreenId dmsScreenId) const
1340e0dac50fSopenharmony_ci{
1341e0dac50fSopenharmony_ci    ScreenId rsScreenId = SCREEN_ID_INVALID;
1342e0dac50fSopenharmony_ci    ConvertToRsScreenId(dmsScreenId, rsScreenId);
1343e0dac50fSopenharmony_ci    return rsScreenId;
1344e0dac50fSopenharmony_ci}
1345e0dac50fSopenharmony_ci
1346e0dac50fSopenharmony_cibool AbstractScreenController::ScreenIdManager::ConvertToDmsScreenId(ScreenId rsScreenId, ScreenId& dmsScreenId) const
1347e0dac50fSopenharmony_ci{
1348e0dac50fSopenharmony_ci    auto iter = rs2DmsScreenIdMap_.find(rsScreenId);
1349e0dac50fSopenharmony_ci    if (iter == rs2DmsScreenIdMap_.end()) {
1350e0dac50fSopenharmony_ci        return false;
1351e0dac50fSopenharmony_ci    }
1352e0dac50fSopenharmony_ci    dmsScreenId = iter->second;
1353e0dac50fSopenharmony_ci    return true;
1354e0dac50fSopenharmony_ci}
1355e0dac50fSopenharmony_ci
1356e0dac50fSopenharmony_ciScreenId AbstractScreenController::ScreenIdManager::ConvertToDmsScreenId(ScreenId rsScreenId) const
1357e0dac50fSopenharmony_ci{
1358e0dac50fSopenharmony_ci    ScreenId dmsScreenId = SCREEN_ID_INVALID;
1359e0dac50fSopenharmony_ci    ConvertToDmsScreenId(rsScreenId, dmsScreenId);
1360e0dac50fSopenharmony_ci    return dmsScreenId;
1361e0dac50fSopenharmony_ci}
1362e0dac50fSopenharmony_ci
1363e0dac50fSopenharmony_civoid AbstractScreenController::NotifyScreenConnected(sptr<ScreenInfo> screenInfo) const
1364e0dac50fSopenharmony_ci{
1365e0dac50fSopenharmony_ci    if (screenInfo == nullptr) {
1366e0dac50fSopenharmony_ci        WLOGFE("NotifyScreenConnected error, screenInfo is nullptr.");
1367e0dac50fSopenharmony_ci        return;
1368e0dac50fSopenharmony_ci    }
1369e0dac50fSopenharmony_ci    auto task = [=] {
1370e0dac50fSopenharmony_ci        WLOGFI("NotifyScreenConnected,  screenId:%{public}" PRIu64"", screenInfo->GetScreenId());
1371e0dac50fSopenharmony_ci        DisplayManagerAgentController::GetInstance().OnScreenConnect(screenInfo);
1372e0dac50fSopenharmony_ci    };
1373e0dac50fSopenharmony_ci    controllerHandler_->PostTask(task, "wms:OnScreenConnect", 0, AppExecFwk::EventQueue::Priority::HIGH);
1374e0dac50fSopenharmony_ci}
1375e0dac50fSopenharmony_ci
1376e0dac50fSopenharmony_civoid AbstractScreenController::NotifyScreenDisconnected(ScreenId screenId) const
1377e0dac50fSopenharmony_ci{
1378e0dac50fSopenharmony_ci    auto task = [=] {
1379e0dac50fSopenharmony_ci        WLOGFI("NotifyScreenDisconnected,  screenId:%{public}" PRIu64"", screenId);
1380e0dac50fSopenharmony_ci        DisplayManagerAgentController::GetInstance().OnScreenDisconnect(screenId);
1381e0dac50fSopenharmony_ci    };
1382e0dac50fSopenharmony_ci    controllerHandler_->PostTask(task, "wms:NotifyScreenDisconnected", 0, AppExecFwk::EventQueue::Priority::HIGH);
1383e0dac50fSopenharmony_ci}
1384e0dac50fSopenharmony_ci
1385e0dac50fSopenharmony_civoid AbstractScreenController::NotifyScreenChanged(sptr<ScreenInfo> screenInfo, ScreenChangeEvent event) const
1386e0dac50fSopenharmony_ci{
1387e0dac50fSopenharmony_ci    if (screenInfo == nullptr) {
1388e0dac50fSopenharmony_ci        WLOGFE("NotifyScreenChanged error, screenInfo is nullptr.");
1389e0dac50fSopenharmony_ci        return;
1390e0dac50fSopenharmony_ci    }
1391e0dac50fSopenharmony_ci    auto task = [=] {
1392e0dac50fSopenharmony_ci        WLOGFI("NotifyScreenChanged,  screenId:%{public}" PRIu64"", screenInfo->GetScreenId());
1393e0dac50fSopenharmony_ci        DisplayManagerAgentController::GetInstance().OnScreenChange(screenInfo, event);
1394e0dac50fSopenharmony_ci    };
1395e0dac50fSopenharmony_ci    controllerHandler_->PostTask(task, "wms:OnScreenChange", 0, AppExecFwk::EventQueue::Priority::HIGH);
1396e0dac50fSopenharmony_ci}
1397e0dac50fSopenharmony_ci
1398e0dac50fSopenharmony_civoid AbstractScreenController::NotifyScreenGroupChanged(
1399e0dac50fSopenharmony_ci    const sptr<ScreenInfo>& screenInfo, ScreenGroupChangeEvent event) const
1400e0dac50fSopenharmony_ci{
1401e0dac50fSopenharmony_ci    if (screenInfo == nullptr) {
1402e0dac50fSopenharmony_ci        WLOGFE("screenInfo is nullptr.");
1403e0dac50fSopenharmony_ci        return;
1404e0dac50fSopenharmony_ci    }
1405e0dac50fSopenharmony_ci    std::string trigger = SysCapUtil::GetClientName();
1406e0dac50fSopenharmony_ci    auto task = [=] {
1407e0dac50fSopenharmony_ci        WLOGFI("screenId:%{public}" PRIu64", trigger:[%{public}s]", screenInfo->GetScreenId(), trigger.c_str());
1408e0dac50fSopenharmony_ci        DisplayManagerAgentController::GetInstance().OnScreenGroupChange(trigger, screenInfo, event);
1409e0dac50fSopenharmony_ci    };
1410e0dac50fSopenharmony_ci    controllerHandler_->PostTask(task, "wms:OnScreenGroupChange", 0, AppExecFwk::EventQueue::Priority::HIGH);
1411e0dac50fSopenharmony_ci}
1412e0dac50fSopenharmony_ci
1413e0dac50fSopenharmony_civoid AbstractScreenController::NotifyScreenGroupChanged(
1414e0dac50fSopenharmony_ci    const std::vector<sptr<ScreenInfo>>& screenInfo, ScreenGroupChangeEvent event) const
1415e0dac50fSopenharmony_ci{
1416e0dac50fSopenharmony_ci    if (screenInfo.empty()) {
1417e0dac50fSopenharmony_ci        return;
1418e0dac50fSopenharmony_ci    }
1419e0dac50fSopenharmony_ci    std::string trigger = SysCapUtil::GetClientName();
1420e0dac50fSopenharmony_ci    auto task = [=] {
1421e0dac50fSopenharmony_ci        WLOGFI("trigger:[%{public}s]", trigger.c_str());
1422e0dac50fSopenharmony_ci        DisplayManagerAgentController::GetInstance().OnScreenGroupChange(trigger, screenInfo, event);
1423e0dac50fSopenharmony_ci    };
1424e0dac50fSopenharmony_ci    controllerHandler_->PostTask(task, "wms:NotifyScreenGroupChanged", 0, AppExecFwk::EventQueue::Priority::HIGH);
1425e0dac50fSopenharmony_ci}
1426e0dac50fSopenharmony_ci
1427e0dac50fSopenharmony_cibool AbstractScreenController::SetScreenPowerForAll(ScreenPowerState state,
1428e0dac50fSopenharmony_ci    PowerStateChangeReason reason, bool needToNotify)
1429e0dac50fSopenharmony_ci{
1430e0dac50fSopenharmony_ci    WLOGFI("state:%{public}u, reason:%{public}u", state, reason);
1431e0dac50fSopenharmony_ci    auto screenIds = GetAllScreenIds();
1432e0dac50fSopenharmony_ci    if (screenIds.empty()) {
1433e0dac50fSopenharmony_ci        WLOGFI("no screen info");
1434e0dac50fSopenharmony_ci        return false;
1435e0dac50fSopenharmony_ci    }
1436e0dac50fSopenharmony_ci
1437e0dac50fSopenharmony_ci    ScreenPowerStatus status;
1438e0dac50fSopenharmony_ci    switch (state) {
1439e0dac50fSopenharmony_ci        case ScreenPowerState::POWER_ON: {
1440e0dac50fSopenharmony_ci            status = ScreenPowerStatus::POWER_STATUS_ON;
1441e0dac50fSopenharmony_ci            powerState_ = ScreenPowerState::POWER_ON;
1442e0dac50fSopenharmony_ci            break;
1443e0dac50fSopenharmony_ci        }
1444e0dac50fSopenharmony_ci        case ScreenPowerState::POWER_OFF: {
1445e0dac50fSopenharmony_ci            status = ScreenPowerStatus::POWER_STATUS_OFF;
1446e0dac50fSopenharmony_ci            powerState_ = ScreenPowerState::POWER_OFF;
1447e0dac50fSopenharmony_ci            break;
1448e0dac50fSopenharmony_ci        }
1449e0dac50fSopenharmony_ci        default: {
1450e0dac50fSopenharmony_ci            WLOGFW("SetScreenPowerStatus state not support");
1451e0dac50fSopenharmony_ci            return false;
1452e0dac50fSopenharmony_ci        }
1453e0dac50fSopenharmony_ci    }
1454e0dac50fSopenharmony_ci
1455e0dac50fSopenharmony_ci    bool hasSetScreenPower = false;
1456e0dac50fSopenharmony_ci    for (auto screenId : screenIds) {
1457e0dac50fSopenharmony_ci        auto screen = GetAbstractScreen(screenId);
1458e0dac50fSopenharmony_ci        if (screen == nullptr) {
1459e0dac50fSopenharmony_ci            continue;
1460e0dac50fSopenharmony_ci        }
1461e0dac50fSopenharmony_ci        if (screen->type_ != ScreenType::REAL) {
1462e0dac50fSopenharmony_ci            WLOGD("skip virtual screen %{public}" PRIu64"", screen->dmsId_);
1463e0dac50fSopenharmony_ci            continue;
1464e0dac50fSopenharmony_ci        }
1465e0dac50fSopenharmony_ci        RSInterfaces::GetInstance().SetScreenPowerStatus(screen->rsId_, status);
1466e0dac50fSopenharmony_ci        WLOGFI("set screen power status. rsscreen %{public}" PRIu64", status %{public}u", screen->rsId_, status);
1467e0dac50fSopenharmony_ci        hasSetScreenPower = true;
1468e0dac50fSopenharmony_ci    }
1469e0dac50fSopenharmony_ci    WLOGFI("SetScreenPowerStatus end");
1470e0dac50fSopenharmony_ci    if (!hasSetScreenPower) {
1471e0dac50fSopenharmony_ci        WLOGFI("no real screen");
1472e0dac50fSopenharmony_ci        return false;
1473e0dac50fSopenharmony_ci    }
1474e0dac50fSopenharmony_ci    if (needToNotify) {
1475e0dac50fSopenharmony_ci        return DisplayManagerAgentController::GetInstance().NotifyDisplayPowerEvent(
1476e0dac50fSopenharmony_ci            state == ScreenPowerState::POWER_ON ? DisplayPowerEvent::DISPLAY_ON :
1477e0dac50fSopenharmony_ci            DisplayPowerEvent::DISPLAY_OFF, EventStatus::END);
1478e0dac50fSopenharmony_ci    }
1479e0dac50fSopenharmony_ci    return true;
1480e0dac50fSopenharmony_ci}
1481e0dac50fSopenharmony_ci
1482e0dac50fSopenharmony_ciScreenPowerState AbstractScreenController::GetScreenPower(ScreenId dmsScreenId) const
1483e0dac50fSopenharmony_ci{
1484e0dac50fSopenharmony_ci    uint32_t retryTimes = 0;
1485e0dac50fSopenharmony_ci    bool res = false;
1486e0dac50fSopenharmony_ci    while (retryTimes < MAX_RETRY_NUM) {
1487e0dac50fSopenharmony_ci        {
1488e0dac50fSopenharmony_ci            std::lock_guard<std::recursive_mutex> lock(mutex_);
1489e0dac50fSopenharmony_ci            if (dmsScreenMap_.find(dmsScreenId) != dmsScreenMap_.end()) {
1490e0dac50fSopenharmony_ci                WLOGFI("find screen %{public}" PRIu64"", dmsScreenId);
1491e0dac50fSopenharmony_ci                res = true;
1492e0dac50fSopenharmony_ci                break;
1493e0dac50fSopenharmony_ci            }
1494e0dac50fSopenharmony_ci        }
1495e0dac50fSopenharmony_ci        retryTimes++;
1496e0dac50fSopenharmony_ci        WLOGFW("not find screen, retry %{public}u times", retryTimes);
1497e0dac50fSopenharmony_ci        std::this_thread::sleep_for(std::chrono::milliseconds(RETRY_WAIT_MS));
1498e0dac50fSopenharmony_ci    }
1499e0dac50fSopenharmony_ci    if (retryTimes >= MAX_RETRY_NUM || !res) {
1500e0dac50fSopenharmony_ci        WLOGFE("cannot find screen %{public}" PRIu64"", dmsScreenId);
1501e0dac50fSopenharmony_ci        return ScreenPowerState::INVALID_STATE;
1502e0dac50fSopenharmony_ci    }
1503e0dac50fSopenharmony_ci
1504e0dac50fSopenharmony_ci    ScreenId rsId = ConvertToRsScreenId(dmsScreenId);
1505e0dac50fSopenharmony_ci    auto state = static_cast<ScreenPowerState>(RSInterfaces::GetInstance().GetScreenPowerStatus(rsId));
1506e0dac50fSopenharmony_ci    WLOGFI("GetScreenPower:%{public}u, rsscreen:%{public}" PRIu64".", state, rsId);
1507e0dac50fSopenharmony_ci    return state;
1508e0dac50fSopenharmony_ci}
1509e0dac50fSopenharmony_ci
1510e0dac50fSopenharmony_ciDMError AbstractScreenController::SetVirtualPixelRatio(ScreenId screenId, float virtualPixelRatio)
1511e0dac50fSopenharmony_ci{
1512e0dac50fSopenharmony_ci    WLOGD("set virtual pixel ratio. screen %{public}" PRIu64" virtualPixelRatio %{public}f",
1513e0dac50fSopenharmony_ci        screenId, virtualPixelRatio);
1514e0dac50fSopenharmony_ci    auto screen = GetAbstractScreen(screenId);
1515e0dac50fSopenharmony_ci    if (screen == nullptr) {
1516e0dac50fSopenharmony_ci        WLOGFE("fail to set virtual pixel ratio, cannot find screen %{public}" PRIu64"", screenId);
1517e0dac50fSopenharmony_ci        return DMError::DM_ERROR_NULLPTR;
1518e0dac50fSopenharmony_ci    }
1519e0dac50fSopenharmony_ci    if (screen->isScreenGroup_) {
1520e0dac50fSopenharmony_ci        WLOGE("cannot set virtual pixel ratio to the combination. screen: %{public}" PRIu64"", screenId);
1521e0dac50fSopenharmony_ci        return DMError::DM_ERROR_NULLPTR;
1522e0dac50fSopenharmony_ci    }
1523e0dac50fSopenharmony_ci    if (fabs(screen->virtualPixelRatio_ - virtualPixelRatio) < 1e-6) { // less to 1e-6 mean equal
1524e0dac50fSopenharmony_ci        WLOGE("The density is equivalent to the original value, no update operation is required, aborted.");
1525e0dac50fSopenharmony_ci        return DMError::DM_OK;
1526e0dac50fSopenharmony_ci    }
1527e0dac50fSopenharmony_ci    screen->SetVirtualPixelRatio(virtualPixelRatio);
1528e0dac50fSopenharmony_ci    // Notify rotation event to AbstractDisplayController
1529e0dac50fSopenharmony_ci    if (abstractScreenCallback_ != nullptr) {
1530e0dac50fSopenharmony_ci        abstractScreenCallback_->onChange_(screen, DisplayChangeEvent::DISPLAY_VIRTUAL_PIXEL_RATIO_CHANGED);
1531e0dac50fSopenharmony_ci    }
1532e0dac50fSopenharmony_ci    NotifyScreenChanged(screen->ConvertToScreenInfo(), ScreenChangeEvent::VIRTUAL_PIXEL_RATIO_CHANGED);
1533e0dac50fSopenharmony_ci    return DMError::DM_OK;
1534e0dac50fSopenharmony_ci}
1535e0dac50fSopenharmony_ci} // namespace OHOS::Rosen
1536