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