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