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