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