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