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