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