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