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