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 for (ScreenId screenId : screenIds) {
1038 WLOGFI("ScreenId: %{public}" PRIu64"", screenId);
1039 auto screen = GetAbstractScreen(screenId);
1040 if (screen == nullptr) {
1041 WLOGFW("screen:%{public}" PRIu64" is nullptr", screenId);
1042 continue;
1043 }
1044 auto iter = dmsScreenGroupMap_.find(screen->groupDmsId_);
1045 if (iter == dmsScreenGroupMap_.end()) {
1046 WLOGFW("groupDmsId:%{public}" PRIu64"is not in dmsScreenGroupMap_", screen->groupDmsId_);
1047 continue;
1048 }
1049 sptr<AbstractScreenGroup> screenGroup = iter->second;
1050 if (screenGroup == nullptr) {
1051 WLOGFW("screenGroup:%{public}" PRIu64" is nullptr", screen->groupDmsId_);
1052 continue;
1053 }
1054 if (screenGroup->combination_ != stopCombination) {
1055 WLOGFW("try to stop screen in another combination");
1056 continue;
1057 }
1058 if (screenGroup->combination_ == ScreenCombination::SCREEN_MIRROR &&
1059 screen->dmsId_ == screenGroup->mirrorScreenId_) {
1060 WLOGFW("try to stop main mirror screen");
1061 continue;
1062 }
1063
1064 if (abstractScreenCallback_ != nullptr && CheckScreenInScreenGroup(screen)) {
1065 abstractScreenCallback_->onDisconnect_(screen);
1066 }
1067 bool res = RemoveChildFromGroup(screen, screenGroup);
1068 if (res) {
1069 NotifyScreenGroupChanged(screen->ConvertToScreenInfo(), ScreenGroupChangeEvent::REMOVE_FROM_GROUP);
1070 }
1071 }
1072 return DMError::DM_OK;
1073 }
1074
ChangeScreenGroup(sptr<AbstractScreenGroup> group,const std::vector<ScreenId> & screens,const std::vector<Point> & startPoints,bool filterScreen,ScreenCombination combination)1075 void AbstractScreenController::ChangeScreenGroup(sptr<AbstractScreenGroup> group, const std::vector<ScreenId>& screens,
1076 const std::vector<Point>& startPoints, bool filterScreen, ScreenCombination combination)
1077 {
1078 std::map<ScreenId, bool> removeChildResMap;
1079 std::vector<ScreenId> addScreens;
1080 std::vector<Point> addChildPos;
1081 std::lock_guard<std::recursive_mutex> lock(mutex_);
1082 for (uint64_t i = 0; i != screens.size(); i++) {
1083 ScreenId screenId = screens[i];
1084 WLOGFI("ScreenId: %{public}" PRIu64"", screenId);
1085 auto screen = GetAbstractScreen(screenId);
1086 if (screen == nullptr) {
1087 WLOGFE("screen:%{public}" PRIu64" is nullptr", screenId);
1088 continue;
1089 }
1090 WLOGFI("Screen->groupDmsId_: %{public}" PRIu64"", screen->groupDmsId_);
1091 if (filterScreen && screen->groupDmsId_ == group->dmsId_ && group->HasChild(screen->dmsId_)) {
1092 continue;
1093 }
1094 if (abstractScreenCallback_ != nullptr && CheckScreenInScreenGroup(screen)) {
1095 abstractScreenCallback_->onDisconnect_(screen);
1096 }
1097 auto originGroup = RemoveFromGroupLocked(screen);
1098 addChildPos.emplace_back(startPoints[i]);
1099 removeChildResMap[screenId] = originGroup != nullptr;
1100 addScreens.emplace_back(screenId);
1101 }
1102 group->combination_ = combination;
1103 AddScreenToGroup(group, addScreens, addChildPos, removeChildResMap);
1104 }
1105
AddScreenToGroup(sptr<AbstractScreenGroup> group,const std::vector<ScreenId> & addScreens,const std::vector<Point> & addChildPos,std::map<ScreenId,bool> & removeChildResMap)1106 void AbstractScreenController::AddScreenToGroup(sptr<AbstractScreenGroup> group,
1107 const std::vector<ScreenId>& addScreens, const std::vector<Point>& addChildPos,
1108 std::map<ScreenId, bool>& removeChildResMap)
1109 {
1110 std::vector<sptr<ScreenInfo>> addToGroup;
1111 std::vector<sptr<ScreenInfo>> removeFromGroup;
1112 std::vector<sptr<ScreenInfo>> changeGroup;
1113 for (uint64_t i = 0; i != addScreens.size(); i++) {
1114 ScreenId screenId = addScreens[i];
1115 sptr<AbstractScreen> screen = GetAbstractScreen(screenId);
1116 if (screen == nullptr) {
1117 continue;
1118 }
1119 Point expandPoint = addChildPos[i];
1120 WLOGFI("screenId: %{public}" PRIu64", Point: %{public}d, %{public}d",
1121 screen->dmsId_, expandPoint.posX_, expandPoint.posY_);
1122 bool addChildRes = group->AddChild(screen, expandPoint);
1123 if (removeChildResMap[screenId] && addChildRes) {
1124 changeGroup.emplace_back(screen->ConvertToScreenInfo());
1125 WLOGFD("changeGroup");
1126 } else if (removeChildResMap[screenId]) {
1127 WLOGFD("removeChild");
1128 removeFromGroup.emplace_back(screen->ConvertToScreenInfo());
1129 } else if (addChildRes) {
1130 WLOGFD("AddChild");
1131 addToGroup.emplace_back(screen->ConvertToScreenInfo());
1132 } else {
1133 WLOGFD("default, AddChild failed");
1134 }
1135 if (abstractScreenCallback_ != nullptr) {
1136 abstractScreenCallback_->onConnect_(screen);
1137 }
1138 }
1139
1140 NotifyScreenGroupChanged(removeFromGroup, ScreenGroupChangeEvent::REMOVE_FROM_GROUP);
1141 NotifyScreenGroupChanged(changeGroup, ScreenGroupChangeEvent::CHANGE_GROUP);
1142 NotifyScreenGroupChanged(addToGroup, ScreenGroupChangeEvent::ADD_TO_GROUP);
1143 }
1144
MakeExpand(std::vector<ScreenId> screenIds,std::vector<Point> startPoints)1145 bool AbstractScreenController::MakeExpand(std::vector<ScreenId> screenIds, std::vector<Point> startPoints)
1146 {
1147 ScreenId defaultScreenId = GetDefaultAbstractScreenId();
1148 WLOGI("MakeExpand, defaultScreenId:%{public}" PRIu64"", defaultScreenId);
1149 auto defaultScreen = GetAbstractScreen(defaultScreenId);
1150 if (defaultScreen == nullptr) {
1151 return false;
1152 }
1153 auto group = GetAbstractScreenGroup(defaultScreen->groupDmsId_);
1154 if (group == nullptr) {
1155 return false;
1156 }
1157 bool filterExpandScreen = group->combination_ == ScreenCombination::SCREEN_EXPAND;
1158 ChangeScreenGroup(group, screenIds, startPoints, filterExpandScreen, ScreenCombination::SCREEN_EXPAND);
1159 WLOGFI("MakeExpand success");
1160 return true;
1161 }
1162
RemoveVirtualScreenFromGroup(std::vector<ScreenId> screens)1163 void AbstractScreenController::RemoveVirtualScreenFromGroup(std::vector<ScreenId> screens)
1164 {
1165 if (screens.empty()) {
1166 return;
1167 }
1168 std::vector<sptr<ScreenInfo>> removeFromGroup;
1169 for (ScreenId screenId : screens) {
1170 auto screen = GetAbstractScreen(screenId);
1171 if (screen == nullptr || screen->type_ != ScreenType::VIRTUAL) {
1172 continue;
1173 }
1174 auto originGroup = GetAbstractScreenGroup(screen->groupDmsId_);
1175 if (originGroup == nullptr) {
1176 continue;
1177 }
1178 if (!originGroup->HasChild(screenId)) {
1179 continue;
1180 }
1181 if (abstractScreenCallback_ != nullptr && CheckScreenInScreenGroup(screen)) {
1182 abstractScreenCallback_->onDisconnect_(screen);
1183 }
1184 RemoveFromGroupLocked(screen);
1185 removeFromGroup.emplace_back(screen->ConvertToScreenInfo());
1186 }
1187 NotifyScreenGroupChanged(removeFromGroup, ScreenGroupChangeEvent::REMOVE_FROM_GROUP);
1188 }
1189
OnRemoteDied(const sptr<IRemoteObject> & agent)1190 bool AbstractScreenController::OnRemoteDied(const sptr<IRemoteObject>& agent)
1191 {
1192 if (agent == nullptr) {
1193 return false;
1194 }
1195 std::lock_guard<std::recursive_mutex> lock(mutex_);
1196 auto agentIter = screenAgentMap_.find(agent);
1197 if (agentIter != screenAgentMap_.end()) {
1198 while (screenAgentMap_[agent].size() > 0) {
1199 auto diedId = screenAgentMap_[agent][0];
1200 WLOGI("destroy screenId in OnRemoteDied: %{public}" PRIu64"", diedId);
1201 DMError res = DestroyVirtualScreen(diedId);
1202 if (res != DMError::DM_OK) {
1203 WLOGE("destroy failed in OnRemoteDied: %{public}" PRIu64"", diedId);
1204 }
1205 }
1206 screenAgentMap_.erase(agent);
1207 }
1208 return true;
1209 }
1210
CreateAndGetNewScreenId(ScreenId rsScreenId)1211 ScreenId AbstractScreenController::ScreenIdManager::CreateAndGetNewScreenId(ScreenId rsScreenId)
1212 {
1213 ScreenId dmsScreenId = dmsScreenCount_++;
1214 if (dms2RsScreenIdMap_.find(dmsScreenId) != dms2RsScreenIdMap_.end()) {
1215 WLOGFW("dmsScreenId: %{public}" PRIu64" exit in dms2RsScreenIdMap_, warning.", dmsScreenId);
1216 }
1217 dms2RsScreenIdMap_[dmsScreenId] = rsScreenId;
1218 if (rsScreenId == SCREEN_ID_INVALID) {
1219 return dmsScreenId;
1220 }
1221 if (rs2DmsScreenIdMap_.find(rsScreenId) != rs2DmsScreenIdMap_.end()) {
1222 WLOGFW("rsScreenId: %{public}" PRIu64" exit in rs2DmsScreenIdMap_, warning.", rsScreenId);
1223 }
1224 rs2DmsScreenIdMap_[rsScreenId] = dmsScreenId;
1225 return dmsScreenId;
1226 }
1227
DeleteScreenId(ScreenId dmsScreenId)1228 bool AbstractScreenController::ScreenIdManager::DeleteScreenId(ScreenId dmsScreenId)
1229 {
1230 auto iter = dms2RsScreenIdMap_.find(dmsScreenId);
1231 if (iter == dms2RsScreenIdMap_.end()) {
1232 return false;
1233 }
1234 ScreenId rsScreenId = iter->second;
1235 dms2RsScreenIdMap_.erase(dmsScreenId);
1236 rs2DmsScreenIdMap_.erase(rsScreenId);
1237 return true;
1238 }
1239
HasDmsScreenId(ScreenId dmsScreenId) const1240 bool AbstractScreenController::ScreenIdManager::HasDmsScreenId(ScreenId dmsScreenId) const
1241 {
1242 return dms2RsScreenIdMap_.find(dmsScreenId) != dms2RsScreenIdMap_.end();
1243 }
1244
HasRsScreenId(ScreenId dmsScreenId) const1245 bool AbstractScreenController::ScreenIdManager::HasRsScreenId(ScreenId dmsScreenId) const
1246 {
1247 return rs2DmsScreenIdMap_.find(dmsScreenId) != rs2DmsScreenIdMap_.end();
1248 }
1249
ConvertToRsScreenId(ScreenId dmsScreenId,ScreenId & rsScreenId) const1250 bool AbstractScreenController::ScreenIdManager::ConvertToRsScreenId(ScreenId dmsScreenId, ScreenId& rsScreenId) const
1251 {
1252 auto iter = dms2RsScreenIdMap_.find(dmsScreenId);
1253 if (iter == dms2RsScreenIdMap_.end()) {
1254 return false;
1255 }
1256 rsScreenId = iter->second;
1257 return true;
1258 }
1259
ConvertToRsScreenId(ScreenId dmsScreenId) const1260 ScreenId AbstractScreenController::ScreenIdManager::ConvertToRsScreenId(ScreenId dmsScreenId) const
1261 {
1262 ScreenId rsScreenId = SCREEN_ID_INVALID;
1263 ConvertToRsScreenId(dmsScreenId, rsScreenId);
1264 return rsScreenId;
1265 }
1266
ConvertToDmsScreenId(ScreenId rsScreenId,ScreenId & dmsScreenId) const1267 bool AbstractScreenController::ScreenIdManager::ConvertToDmsScreenId(ScreenId rsScreenId, ScreenId& dmsScreenId) const
1268 {
1269 auto iter = rs2DmsScreenIdMap_.find(rsScreenId);
1270 if (iter == rs2DmsScreenIdMap_.end()) {
1271 return false;
1272 }
1273 dmsScreenId = iter->second;
1274 return true;
1275 }
1276
ConvertToDmsScreenId(ScreenId rsScreenId) const1277 ScreenId AbstractScreenController::ScreenIdManager::ConvertToDmsScreenId(ScreenId rsScreenId) const
1278 {
1279 ScreenId dmsScreenId = SCREEN_ID_INVALID;
1280 ConvertToDmsScreenId(rsScreenId, dmsScreenId);
1281 return dmsScreenId;
1282 }
1283
NotifyScreenConnected(sptr<ScreenInfo> screenInfo) const1284 void AbstractScreenController::NotifyScreenConnected(sptr<ScreenInfo> screenInfo) const
1285 {
1286 if (screenInfo == nullptr) {
1287 WLOGFE("NotifyScreenConnected error, screenInfo is nullptr.");
1288 return;
1289 }
1290 auto task = [=] {
1291 WLOGFI("NotifyScreenConnected, screenId:%{public}" PRIu64"", screenInfo->GetScreenId());
1292 DisplayManagerAgentController::GetInstance().OnScreenConnect(screenInfo);
1293 };
1294 controllerHandler_->PostTask(task, AppExecFwk::EventQueue::Priority::HIGH);
1295 }
1296
NotifyScreenDisconnected(ScreenId screenId) const1297 void AbstractScreenController::NotifyScreenDisconnected(ScreenId screenId) const
1298 {
1299 auto task = [=] {
1300 WLOGFI("NotifyScreenDisconnected, screenId:%{public}" PRIu64"", screenId);
1301 DisplayManagerAgentController::GetInstance().OnScreenDisconnect(screenId);
1302 };
1303 controllerHandler_->PostTask(task, AppExecFwk::EventQueue::Priority::HIGH);
1304 }
1305
NotifyScreenChanged(sptr<ScreenInfo> screenInfo,ScreenChangeEvent event) const1306 void AbstractScreenController::NotifyScreenChanged(sptr<ScreenInfo> screenInfo, ScreenChangeEvent event) const
1307 {
1308 if (screenInfo == nullptr) {
1309 WLOGFE("NotifyScreenChanged error, screenInfo is nullptr.");
1310 return;
1311 }
1312 auto task = [=] {
1313 WLOGFI("NotifyScreenChanged, screenId:%{public}" PRIu64"", screenInfo->GetScreenId());
1314 DisplayManagerAgentController::GetInstance().OnScreenChange(screenInfo, event);
1315 };
1316 controllerHandler_->PostTask(task, AppExecFwk::EventQueue::Priority::HIGH);
1317 }
1318
NotifyScreenGroupChanged(const sptr<ScreenInfo> & screenInfo,ScreenGroupChangeEvent event) const1319 void AbstractScreenController::NotifyScreenGroupChanged(
1320 const sptr<ScreenInfo>& screenInfo, ScreenGroupChangeEvent event) const
1321 {
1322 if (screenInfo == nullptr) {
1323 WLOGFE("screenInfo is nullptr.");
1324 return;
1325 }
1326 std::string trigger = SysCapUtil::GetClientName();
1327 auto task = [=] {
1328 WLOGFI("screenId:%{public}" PRIu64", trigger:[%{public}s]", screenInfo->GetScreenId(), trigger.c_str());
1329 DisplayManagerAgentController::GetInstance().OnScreenGroupChange(trigger, screenInfo, event);
1330 };
1331 controllerHandler_->PostTask(task, AppExecFwk::EventQueue::Priority::HIGH);
1332 }
1333
NotifyScreenGroupChanged(const std::vector<sptr<ScreenInfo>> & screenInfo,ScreenGroupChangeEvent event) const1334 void AbstractScreenController::NotifyScreenGroupChanged(
1335 const std::vector<sptr<ScreenInfo>>& screenInfo, ScreenGroupChangeEvent event) const
1336 {
1337 if (screenInfo.empty()) {
1338 return;
1339 }
1340 std::string trigger = SysCapUtil::GetClientName();
1341 auto task = [=] {
1342 WLOGFI("trigger:[%{public}s]", trigger.c_str());
1343 DisplayManagerAgentController::GetInstance().OnScreenGroupChange(trigger, screenInfo, event);
1344 };
1345 controllerHandler_->PostTask(task, AppExecFwk::EventQueue::Priority::HIGH);
1346 }
1347
SetScreenPowerForAll(ScreenPowerState state,PowerStateChangeReason reason,bool needToNotify)1348 bool AbstractScreenController::SetScreenPowerForAll(ScreenPowerState state,
1349 PowerStateChangeReason reason, bool needToNotify)
1350 {
1351 WLOGFI("state:%{public}u, reason:%{public}u", state, reason);
1352 auto screenIds = GetAllScreenIds();
1353 if (screenIds.empty()) {
1354 WLOGFI("no screen info");
1355 return false;
1356 }
1357
1358 ScreenPowerStatus status;
1359 switch (state) {
1360 case ScreenPowerState::POWER_ON: {
1361 status = ScreenPowerStatus::POWER_STATUS_ON;
1362 powerState_ = ScreenPowerState::POWER_ON;
1363 break;
1364 }
1365 case ScreenPowerState::POWER_OFF: {
1366 status = ScreenPowerStatus::POWER_STATUS_OFF;
1367 powerState_ = ScreenPowerState::POWER_OFF;
1368 break;
1369 }
1370 default: {
1371 WLOGFW("SetScreenPowerStatus state not support");
1372 return false;
1373 }
1374 }
1375
1376 bool hasSetScreenPower = false;
1377 for (auto screenId : screenIds) {
1378 auto screen = GetAbstractScreen(screenId);
1379 if (screen == nullptr) {
1380 continue;
1381 }
1382 if (screen->type_ != ScreenType::REAL) {
1383 WLOGD("skip virtual screen %{public}" PRIu64"", screen->dmsId_);
1384 continue;
1385 }
1386 RSInterfaces::GetInstance().SetScreenPowerStatus(screen->rsId_, status);
1387 WLOGFI("set screen power status. rsscreen %{public}" PRIu64", status %{public}u", screen->rsId_, status);
1388 hasSetScreenPower = true;
1389 }
1390 WLOGFI("SetScreenPowerStatus end");
1391 if (!hasSetScreenPower) {
1392 WLOGFI("no real screen");
1393 return false;
1394 }
1395 if (needToNotify) {
1396 return DisplayManagerAgentController::GetInstance().NotifyDisplayPowerEvent(
1397 state == ScreenPowerState::POWER_ON ? DisplayPowerEvent::DISPLAY_ON :
1398 DisplayPowerEvent::DISPLAY_OFF, EventStatus::END);
1399 }
1400 return true;
1401 }
1402
GetScreenPower(ScreenId dmsScreenId) const1403 ScreenPowerState AbstractScreenController::GetScreenPower(ScreenId dmsScreenId) const
1404 {
1405 {
1406 std::lock_guard<std::recursive_mutex> lock(mutex_);
1407 if (dmsScreenMap_.find(dmsScreenId) == dmsScreenMap_.end()) {
1408 WLOGFE("cannot find screen %{public}" PRIu64"", dmsScreenId);
1409 return ScreenPowerState::INVALID_STATE;
1410 }
1411 }
1412
1413 ScreenId rsId = ConvertToRsScreenId(dmsScreenId);
1414 auto state = static_cast<ScreenPowerState>(RSInterfaces::GetInstance().GetScreenPowerStatus(rsId));
1415 WLOGFI("GetScreenPower:%{public}u, rsscreen:%{public}" PRIu64".", state, rsId);
1416 return state;
1417 }
1418
SetVirtualPixelRatio(ScreenId screenId,float virtualPixelRatio)1419 DMError AbstractScreenController::SetVirtualPixelRatio(ScreenId screenId, float virtualPixelRatio)
1420 {
1421 WLOGD("set virtual pixel ratio. screen %{public}" PRIu64" virtualPixelRatio %{public}f",
1422 screenId, virtualPixelRatio);
1423 auto screen = GetAbstractScreen(screenId);
1424 if (screen == nullptr) {
1425 WLOGFE("fail to set virtual pixel ratio, cannot find screen %{public}" PRIu64"", screenId);
1426 return DMError::DM_ERROR_NULLPTR;
1427 }
1428 if (screen->isScreenGroup_) {
1429 WLOGE("cannot set virtual pixel ratio to the combination. screen: %{public}" PRIu64"", screenId);
1430 return DMError::DM_ERROR_NULLPTR;
1431 }
1432 if (fabs(screen->virtualPixelRatio_ - virtualPixelRatio) < 1e-6) {
1433 WLOGE("The density is equivalent to the original value, no update operation is required, aborted.");
1434 return DMError::DM_OK;
1435 }
1436 screen->SetVirtualPixelRatio(virtualPixelRatio);
1437 // Notify rotation event to AbstractDisplayController
1438 if (abstractScreenCallback_ != nullptr) {
1439 abstractScreenCallback_->onChange_(screen, DisplayChangeEvent::DISPLAY_VIRTUAL_PIXEL_RATIO_CHANGED);
1440 }
1441 NotifyScreenChanged(screen->ConvertToScreenInfo(), ScreenChangeEvent::VIRTUAL_PIXEL_RATIO_CHANGED);
1442 return DMError::DM_OK;
1443 }
1444 } // namespace OHOS::Rosen
1445