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