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