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