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 "rs_screen_manager.h"
17
18 #include "pipeline/rs_display_render_node.h"
19 #include "pipeline/rs_main_thread.h"
20 #include "platform/common/rs_log.h"
21 #include "vsync_sampler.h"
22
23 namespace OHOS {
24 namespace Rosen {
25 using namespace HiviewDFX;
26 namespace impl {
27 std::once_flag RSScreenManager::createFlag_;
28 sptr<OHOS::Rosen::RSScreenManager> RSScreenManager::instance_ = nullptr;
29
GetInstance()30 sptr<OHOS::Rosen::RSScreenManager> RSScreenManager::GetInstance() noexcept
31 {
32 std::call_once(createFlag_, []() {
33 instance_ = new RSScreenManager();
34 });
35
36 return instance_;
37 }
38
RSScreenManager()39 RSScreenManager::RSScreenManager()
40 {
41 }
42
~RSScreenManager()43 RSScreenManager::~RSScreenManager() noexcept
44 {
45 }
46
Init()47 bool RSScreenManager::Init() noexcept
48 {
49 composer_ = HdiBackend::GetInstance();
50 if (composer_ == nullptr) {
51 RS_LOGE("RSScreenManager %s: Failed to get composer.", __func__);
52 return false;
53 }
54
55 if (composer_->RegScreenHotplug(&RSScreenManager::OnHotPlug, this) == -1) {
56 RS_LOGE("RSScreenManager %s: Failed to register OnHotPlug Func to composer.", __func__);
57 return false;
58 }
59
60 // call ProcessScreenHotPlugEvents() for primary screen immediately in main thread.
61 ProcessScreenHotPlugEvents();
62
63 return true;
64 }
65
OnHotPlug(std::shared_ptr<HdiOutput> & output,bool connected,void * data)66 void RSScreenManager::OnHotPlug(std::shared_ptr<HdiOutput> &output, bool connected, void *data)
67 {
68 if (output == nullptr) {
69 RS_LOGE("RSScreenManager %s: output is nullptr.", __func__);
70 return;
71 }
72
73 RSScreenManager *screenManager = nullptr;
74 if (data != nullptr) {
75 screenManager = static_cast<RSScreenManager *>(data);
76 } else {
77 screenManager = static_cast<RSScreenManager *>(RSScreenManager::GetInstance().GetRefPtr());
78 }
79
80 if (screenManager == nullptr) {
81 RS_LOGE("RSScreenManager %s: Failed to find RSScreenManager instance.", __func__);
82 return;
83 }
84
85 screenManager->OnHotPlugEvent(output, connected);
86 }
87
OnHotPlugEvent(std::shared_ptr<HdiOutput> & output,bool connected)88 void RSScreenManager::OnHotPlugEvent(std::shared_ptr<HdiOutput> &output, bool connected)
89 {
90 {
91 std::lock_guard<std::mutex> lock(mutex_);
92 pendingHotPlugEvents_.emplace_back(ScreenHotPlugEvent{output, connected});
93 }
94
95 // This func would be called in main thread first time immediately after calling composer_->RegScreenHotplug,
96 // but at this time the RSMainThread object would not be ready to handle this, so we need to call
97 // ProcessScreenHotPlugEvents() after this func in RSScreenManager::Init().
98
99 // Normally, this func would be called in hdi's hw-ipc threads(but sometimes in main thread, maybe),
100 // so we should notify the RSMainThread to postTask to call ProcessScreenHotPlugEvents().
101 auto mainThread = RSMainThread::Instance();
102 if (mainThread == nullptr) {
103 return;
104 }
105 mainThread->RequestNextVSync();
106 }
107
ProcessScreenHotPlugEvents()108 void RSScreenManager::ProcessScreenHotPlugEvents()
109 {
110 std::lock_guard<std::mutex> lock(mutex_);
111 for (auto &event : pendingHotPlugEvents_) {
112 if (event.connected) {
113 ProcessScreenConnectedLocked(event.output);
114 } else {
115 ProcessScreenDisConnectedLocked(event.output);
116 }
117 }
118 for (auto id : connectedIds_) {
119 for (auto &cb : screenChangeCallbacks_) {
120 cb->OnScreenChanged(id, ScreenEvent::CONNECTED);
121 }
122 }
123 mipiCheckInFirstHotPlugEvent_ = true;
124 pendingHotPlugEvents_.clear();
125 connectedIds_.clear();
126 }
127
ProcessScreenConnectedLocked(std::shared_ptr<HdiOutput> & output)128 void RSScreenManager::ProcessScreenConnectedLocked(std::shared_ptr<HdiOutput> &output)
129 {
130 if (output == nullptr) {
131 RS_LOGE("RSScreenManager %s: output is nullptr.", __func__);
132 return;
133 }
134
135 bool isVirtual = false;
136 ScreenId id = ToScreenId(output->GetScreenId());
137
138 if (screens_.count(id) == 1) {
139 RS_LOGW("RSScreenManager %s The screen for id %" PRIu64 " already existed.", __func__, id);
140
141 // [PLANNING]: should we erase it and create a new one?
142 for (auto &cb : screenChangeCallbacks_) {
143 cb->OnScreenChanged(id, ScreenEvent::DISCONNECTED);
144 }
145 screens_.erase(id);
146 }
147
148 screens_[id] = std::make_unique<RSScreen>(id, isVirtual, output, nullptr);
149
150 auto vsyncSampler = CreateVSyncSampler();
151 if (vsyncSampler != nullptr) {
152 vsyncSampler->RegSetScreenVsyncEnabledCallback([this, id](bool enabled) {
153 auto mainThread = RSMainThread::Instance();
154 if (mainThread == nullptr) {
155 RS_LOGE("SetScreenVsyncEnabled:%{public}d failed, get RSMainThread failed", enabled);
156 return;
157 }
158 mainThread->PostTask([this, id, enabled]() {
159 if (screens_[id] == nullptr) {
160 RS_LOGE("SetScreenVsyncEnabled:%{public}d failed, screen %{public}ld not found", enabled, id);
161 return;
162 }
163 screens_[id]->SetScreenVsyncEnabled(enabled);
164 });
165 });
166 } else {
167 RS_LOGE("RegSetScreenVsyncEnabledCallback failed, vsyncSampler is null");
168 }
169
170 if (screens_[id]->GetCapability().type == InterfaceType::DISP_INTF_MIPI) {
171 if (!mipiCheckInFirstHotPlugEvent_) {
172 defaultScreenId_ = id;
173 }
174 mipiCheckInFirstHotPlugEvent_ = true;
175 } else if (defaultScreenId_ == INVALID_SCREEN_ID) {
176 defaultScreenId_ = id;
177 }
178
179 RS_LOGI("RSScreenManager %s: A new screen(id %" PRIu64 ") connected.", __func__, id);
180 connectedIds_.emplace_back(id);
181 }
182
ProcessScreenDisConnectedLocked(std::shared_ptr<HdiOutput> & output)183 void RSScreenManager::ProcessScreenDisConnectedLocked(std::shared_ptr<HdiOutput> &output)
184 {
185 ScreenId id = ToScreenId(output->GetScreenId());
186
187 if (screens_.count(id) == 0) {
188 RS_LOGW("RSScreenManager %s: There is no screen for id %" PRIu64, __func__, id);
189 } else {
190 for (auto &cb : screenChangeCallbacks_) {
191 cb->OnScreenChanged(id, ScreenEvent::DISCONNECTED);
192 }
193 screens_.erase(id);
194 RS_LOGI("RSScreenManager %s: Screen(id %" PRIu64 ") disconnected.", __func__, id);
195 }
196 if (screenPowerStatus_.count(id) != 0) {
197 screenPowerStatus_.erase(id);
198 }
199 if (id == defaultScreenId_) {
200 HandleDefaultScreenDisConnectedLocked();
201 }
202 }
203
204 // If the previous primary screen disconnected, we traversal the left screens
205 // and find the first physical screen to be the default screen.
206 // If there was no physical screen left, we set the first screen as default, no matter what type it is.
207 // At last, if no screen left, we set Default Screen Id to INVALID_SCREEN_ID.
HandleDefaultScreenDisConnectedLocked()208 void RSScreenManager::HandleDefaultScreenDisConnectedLocked()
209 {
210 defaultScreenId_ = INVALID_SCREEN_ID;
211 for (const auto &[id, screen] : screens_) {
212 if (!screen->IsVirtual()) {
213 defaultScreenId_ = id;
214 break;
215 }
216 }
217
218 if (defaultScreenId_ == INVALID_SCREEN_ID) {
219 if (!screens_.empty()) {
220 defaultScreenId_ = screens_.cbegin()->first;
221 }
222 }
223 }
224
SetDefaultScreenId(ScreenId id)225 void RSScreenManager::SetDefaultScreenId(ScreenId id)
226 {
227 std::lock_guard<std::mutex> lock(mutex_);
228 defaultScreenId_ = id;
229 }
230
SetScreenMirror(ScreenId id,ScreenId toMirror)231 void RSScreenManager::SetScreenMirror(ScreenId id, ScreenId toMirror)
232 {
233 std::lock_guard<std::mutex> lock(mutex_);
234
235 if (screens_.count(id) == 0) {
236 RS_LOGW("RSScreenManager %s: There is no screen for id %" PRIu64 ".", __func__, id);
237 return;
238 }
239
240 screens_[id]->SetMirror(toMirror);
241 }
242
GenerateVirtualScreenIdLocked()243 ScreenId RSScreenManager::GenerateVirtualScreenIdLocked()
244 {
245 if (!freeVirtualScreenIds_.empty()) {
246 ScreenId id = freeVirtualScreenIds_.front();
247 freeVirtualScreenIds_.pop();
248 return id;
249 }
250
251 // The left 32 bits is for virtual screen id.
252 return (static_cast<ScreenId>(maxVirtualScreenNum_++) << 32) | 0xffffffffu;
253 }
254
ReuseVirtualScreenIdLocked(ScreenId id)255 void RSScreenManager::ReuseVirtualScreenIdLocked(ScreenId id)
256 {
257 freeVirtualScreenIds_.push(id);
258 }
259
GetMirrorScreenId(ScreenId id)260 ScreenId RSScreenManager::GetMirrorScreenId(ScreenId id)
261 {
262 ScreenId mirroredId = INVALID_SCREEN_ID;
263 auto mainThread = RSMainThread::Instance();
264 if (mainThread == nullptr) {
265 return mirroredId;
266 }
267
268 const auto& nodeMap = mainThread->GetContext().GetNodeMap();
269 nodeMap.TraversalNodes([&id, &mirroredId](const std::shared_ptr<RSBaseRenderNode>& node) {
270 if (node == nullptr || !node->IsInstanceOf<RSDisplayRenderNode>()) {
271 return;
272 }
273 RSDisplayRenderNode& displayNode = *(RSBaseRenderNode::ReinterpretCast<RSDisplayRenderNode>(node));
274 if (displayNode.GetScreenId() != id) {
275 return;
276 }
277 std::shared_ptr<RSDisplayRenderNode> mirroredNode = displayNode.GetMirrorSource().lock();
278 if (mirroredNode != nullptr) {
279 mirroredId = mirroredNode->GetScreenId();
280 }
281 });
282 return mirroredId;
283 }
284
285 // The main screen resolution can be changed by the mirrored screen.
MirrorChangeDefaultScreenResolution(ScreenId id,uint32_t width,uint32_t height)286 void RSScreenManager::MirrorChangeDefaultScreenResolution(ScreenId id, uint32_t width, uint32_t height)
287 {
288 if (screens_.count(id) == 0) {
289 RS_LOGD("RSScreenManager %s: set fails because no screen access is currently available!", __func__);
290 return;
291 }
292
293 ScreenId mirroredId = GetMirrorScreenId(id);
294 if (mirroredId == INVALID_SCREEN_ID) {
295 RS_LOGD("RSScreenManager %s: mirror screen is invalid.", __func__);
296 return;
297 }
298 ScreenId mainId = GetDefaultScreenId();
299 if (mirroredId == mainId) {
300 bool resolutionSetSuccess = false;
301 std::vector<DisplayModeInfo> mainMode = screens_.at(mainId)->GetSupportedModes();
302 for (uint32_t i = 0; i < mainMode.size(); i++) {
303 if (static_cast<uint32_t>(mainMode[i].width) == width &&
304 static_cast<uint32_t>(mainMode[i].height) == height) {
305 screens_.at(mainId)->SetActiveMode(i);
306 resolutionSetSuccess = true;
307 break;
308 }
309 }
310 if (!resolutionSetSuccess) {
311 RS_LOGD("RSScreenManager %s: not support the current resolution!", __func__);
312 }
313 }
314 }
315
GetVirtualScreenResolutionLocked(ScreenId id,RSVirtualScreenResolution & virtualScreenResolution) const316 void RSScreenManager::GetVirtualScreenResolutionLocked(ScreenId id,
317 RSVirtualScreenResolution& virtualScreenResolution) const
318 {
319 if (screens_.count(id) == 0) {
320 RS_LOGW("RSScreenManager %s: There is no screen for id %" PRIu64 ".", __func__, id);
321 return;
322 }
323
324 virtualScreenResolution.SetVirtualScreenWidth(static_cast<uint32_t>(screens_.at(id)->Width()));
325 virtualScreenResolution.SetVirtualScreenHeight(static_cast<uint32_t>(screens_.at(id)->Height()));
326 }
327
GetScreenActiveModeLocked(ScreenId id,RSScreenModeInfo & screenModeInfo) const328 void RSScreenManager::GetScreenActiveModeLocked(ScreenId id, RSScreenModeInfo& screenModeInfo) const
329 {
330 if (screens_.count(id) == 0) {
331 RS_LOGW("RSScreenManager %s: There is no screen for id %" PRIu64 ".", __func__, id);
332 return;
333 }
334
335 auto modeInfo = screens_.at(id)->GetActiveMode();
336 if (!modeInfo) {
337 RS_LOGE("RSScreenManager %s: Failed to get active mode for screen %" PRIu64 ".", __func__, id);
338 return;
339 }
340
341 screenModeInfo.SetScreenWidth(modeInfo->width);
342 screenModeInfo.SetScreenHeight(modeInfo->height);
343 screenModeInfo.SetScreenRefreshRate(modeInfo->freshRate);
344 screenModeInfo.SetScreenModeId(screens_.at(id)->GetActiveModePosByModeId(modeInfo->id));
345 }
346
GetScreenSupportedModesLocked(ScreenId id) const347 std::vector<RSScreenModeInfo> RSScreenManager::GetScreenSupportedModesLocked(ScreenId id) const
348 {
349 std::vector<RSScreenModeInfo> screenSupportedModes;
350 if (screens_.count(id) == 0) {
351 RS_LOGW("RSScreenManager %s: There is no screen for id %" PRIu64 ".", __func__, id);
352 return screenSupportedModes;
353 }
354
355 const auto& displaySupportedModes = screens_.at(id)->GetSupportedModes();
356 screenSupportedModes.resize(displaySupportedModes.size());
357 for (decltype(displaySupportedModes.size()) idx = 0; idx < displaySupportedModes.size(); ++idx) {
358 screenSupportedModes[idx].SetScreenWidth(displaySupportedModes[idx].width);
359 screenSupportedModes[idx].SetScreenHeight(displaySupportedModes[idx].height);
360 screenSupportedModes[idx].SetScreenRefreshRate(displaySupportedModes[idx].freshRate);
361 screenSupportedModes[idx].SetScreenModeId(displaySupportedModes[idx].id);
362 }
363 return screenSupportedModes;
364 }
365
GetScreenCapabilityLocked(ScreenId id) const366 RSScreenCapability RSScreenManager::GetScreenCapabilityLocked(ScreenId id) const
367 {
368 RSScreenCapability screenCapability;
369 if (screens_.count(id) == 0) {
370 RS_LOGW("RSScreenManager %s: There is no screen for id %" PRIu64 ".", __func__, id);
371 return screenCapability;
372 }
373 if (screens_.at(id)->IsVirtual()) {
374 RS_LOGW("RSScreenManager %s: only name attribute is valid for virtual screen.", __func__);
375 screenCapability.SetName(screens_.at(id)->Name());
376 return screenCapability;
377 }
378
379 const auto& capability = screens_.at(id)->GetCapability();
380 std::vector<RSScreenProps> props;
381 uint32_t propCount = capability.propertyCount;
382 props.resize(propCount);
383 for (uint32_t propIndex = 0; propIndex < propCount; propIndex++) {
384 props[propIndex] = RSScreenProps(capability.props[propIndex].name, capability.props[propIndex].propId,
385 capability.props[propIndex].value);
386 }
387 screenCapability.SetName(capability.name);
388 screenCapability.SetType(static_cast<ScreenInterfaceType>(capability.type));
389 screenCapability.SetPhyWidth(capability.phyWidth);
390 screenCapability.SetPhyHeight(capability.phyHeight);
391 screenCapability.SetSupportLayers(capability.supportLayers);
392 screenCapability.SetVirtualDispCount(capability.virtualDispCount);
393 screenCapability.SetSupportWriteBack(capability.supportWriteBack);
394 screenCapability.SetProps(props);
395 return screenCapability;
396 }
397
GetScreenPowerStatusLocked(ScreenId id) const398 ScreenPowerStatus RSScreenManager::GetScreenPowerStatusLocked(ScreenId id) const
399 {
400 if (screens_.count(id) == 0) {
401 RS_LOGW("RSScreenManager %s: There is no screen for id %" PRIu64 ".", __func__, id);
402 return INVALID_POWER_STATUS;
403 }
404
405 ScreenPowerStatus status = static_cast<ScreenPowerStatus>(screens_.at(id)->GetPowerStatus());
406 return status;
407 }
408
GetAllScreenIds()409 std::vector<ScreenId> RSScreenManager::GetAllScreenIds()
410 {
411 std::vector<ScreenId> ids;
412 for (std::unordered_map<ScreenId, std::unique_ptr<OHOS::Rosen::RSScreen>>::iterator iter = screens_.begin();
413 iter != screens_.end(); ++iter) {
414 ids.emplace_back(iter->first);
415 }
416 return ids;
417 }
418
CreateVirtualScreen(const std::string & name,uint32_t width,uint32_t height,sptr<Surface> surface,ScreenId mirrorId,int32_t flags)419 ScreenId RSScreenManager::CreateVirtualScreen(
420 const std::string &name,
421 uint32_t width,
422 uint32_t height,
423 sptr<Surface> surface,
424 ScreenId mirrorId,
425 int32_t flags
426 )
427 {
428 std::lock_guard<std::mutex> lock(mutex_);
429
430 if (surface != nullptr) {
431 uint64_t surfaceId = surface->GetUniqueId();
432 for (auto &[_, screen] : screens_) {
433 if (!screen->IsVirtual()) {
434 continue;
435 }
436 auto screenSurface = screen->GetProducerSurface();
437 if (screenSurface == nullptr) {
438 continue;
439 }
440 if (screenSurface->GetUniqueId() == surfaceId) {
441 RS_LOGW("RSScreenManager %s: surface %" PRIu64 " is used, create virtual screen failed!", __func__,
442 surfaceId);
443 return INVALID_SCREEN_ID;
444 }
445 }
446 } else {
447 RS_LOGD("RSScreenManager %s: surface is nullptr.", __func__);
448 }
449
450 VirtualScreenConfigs configs;
451 ScreenId newId = GenerateVirtualScreenIdLocked();
452 configs.id = newId;
453 configs.mirrorId = mirrorId;
454 configs.name = name;
455 configs.width = width;
456 configs.height = height;
457 configs.surface = surface;
458 configs.flags = flags;
459
460 screens_[newId] = std::make_unique<RSScreen>(configs);
461 RS_LOGD("RSScreenManager %s: create virtual screen(id %" PRIu64 ").", __func__, newId);
462 return newId;
463 }
464
SetVirtualScreenSurface(ScreenId id,sptr<Surface> surface)465 int32_t RSScreenManager::SetVirtualScreenSurface(ScreenId id, sptr<Surface> surface)
466 {
467 if (screens_.find(id) == screens_.end()) {
468 return SCREEN_NOT_FOUND;
469 }
470 uint64_t surfaceId = surface->GetUniqueId();
471 for (auto &[screenId, screen] : screens_) {
472 if (!screen->IsVirtual() || screenId == id) {
473 continue;
474 }
475 auto screenSurface = screen->GetProducerSurface();
476 if (screenSurface == nullptr) {
477 continue;
478 }
479 if (screenSurface->GetUniqueId() == surface->GetUniqueId()) {
480 RS_LOGE("RSScreenManager %s: surface %" PRIu64 " is used, set surface failed!", __func__, surfaceId);
481 return SURFACE_NOT_UNIQUE;
482 }
483 }
484 screens_.at(id)->SetProducerSurface(surface);
485 RS_LOGD("RSScreenManager %s: set virtual screen surface success!", __func__);
486 // if SetVirtualScreenSurface success, better to request the next vsync, avoiding prolong black screen
487 auto mainThread = RSMainThread::Instance();
488 if (mainThread != nullptr) {
489 mainThread->RequestNextVSync();
490 }
491 return SUCCESS;
492 }
493
RemoveVirtualScreen(ScreenId id)494 void RSScreenManager::RemoveVirtualScreen(ScreenId id)
495 {
496 std::lock_guard<std::mutex> lock(mutex_);
497
498 RemoveVirtualScreenLocked(id);
499 }
500
RemoveVirtualScreenLocked(ScreenId id)501 void RSScreenManager::RemoveVirtualScreenLocked(ScreenId id)
502 {
503 if (screens_.count(id) == 0) {
504 RS_LOGW("RSScreenManager %s: There is no screen for id %" PRIu64 ".", __func__, id);
505 return;
506 }
507
508 screens_.erase(id);
509
510 // Update other screens' mirrorId.
511 for (auto &[id, screen] : screens_) {
512 if (screen->MirrorId() == id) {
513 screen->SetMirror(INVALID_SCREEN_ID);
514 }
515 }
516 RS_LOGD("RSScreenManager %s: remove virtual screen(id %" PRIu64 ").", __func__, id);
517
518 ReuseVirtualScreenIdLocked(id);
519 }
520
SetScreenActiveMode(ScreenId id,uint32_t modeId)521 void RSScreenManager::SetScreenActiveMode(ScreenId id, uint32_t modeId)
522 {
523 std::lock_guard<std::mutex> lock(mutex_);
524
525 if (screens_.count(id) == 0) {
526 RS_LOGW("RSScreenManager %s: There is no screen for id %" PRIu64 ".", __func__, id);
527 return;
528 }
529 screens_.at(id)->SetActiveMode(modeId);
530
531 // The main screen resolution can be changed on the mirrored physical screen.
532 auto supportedModes = screens_.at(id)->GetSupportedModes();
533 if (modeId >= supportedModes.size()) {
534 RS_LOGE("RSScreenManager %s: set fails because the index is out of bounds.", __func__);
535 return;
536 }
537 uint32_t width = supportedModes[modeId].width;
538 uint32_t height = supportedModes[modeId].height;
539 MirrorChangeDefaultScreenResolution(id, width, height);
540 }
541
SetVirtualScreenResolution(ScreenId id,uint32_t width,uint32_t height)542 int32_t RSScreenManager::SetVirtualScreenResolution(ScreenId id, uint32_t width, uint32_t height)
543 {
544 std::lock_guard<std::mutex> lock(mutex_);
545
546 if (screens_.count(id) == 0) {
547 RS_LOGW("RSScreenManager %s: There is no screen for id %" PRIu64 ".", __func__, id);
548 return SCREEN_NOT_FOUND;
549 }
550 screens_.at(id)->SetResolution(width, height);
551 RS_LOGD("RSScreenManager %s: set virtual screen resolution success", __func__);
552
553 // The main screen resolution can be changed by the mirrored virtual screen.
554 MirrorChangeDefaultScreenResolution(id, width, height);
555
556 return SUCCESS;
557 }
558
SetScreenPowerStatus(ScreenId id,ScreenPowerStatus status)559 void RSScreenManager::SetScreenPowerStatus(ScreenId id, ScreenPowerStatus status)
560 {
561 std::lock_guard<std::mutex> lock(mutex_);
562
563 if (screens_.count(id) == 0) {
564 RS_LOGW("RSScreenManager %s: There is no screen for id %" PRIu64 ".", __func__, id);
565 return;
566 }
567 screens_.at(id)->SetPowerStatus(static_cast<uint32_t>(status));
568
569 /*
570 * If app adds the first frame when power on the screen, delete the code
571 */
572 if (status == ScreenPowerStatus::POWER_STATUS_ON) {
573 auto mainThread = RSMainThread::Instance();
574 if (mainThread == nullptr) {
575 return;
576 }
577 mainThread->SetDirtyFlag();
578 if (screenPowerStatus_.count(id) == 0 || screenPowerStatus_[id] == ScreenPowerStatus::POWER_STATUS_OFF) {
579 mainThread->ForceRefreshForUni();
580 } else {
581 mainThread->RequestNextVSync();
582 }
583
584 RS_LOGI("RSScreenManager %s: Set system power on, request a frame", __func__);
585 }
586 screenPowerStatus_[id] = status;
587 }
588
GetVirtualScreenResolution(ScreenId id,RSVirtualScreenResolution & virtualScreenResolution) const589 void RSScreenManager::GetVirtualScreenResolution(ScreenId id, RSVirtualScreenResolution& virtualScreenResolution) const
590 {
591 std::lock_guard<std::mutex> lock(mutex_);
592
593 GetVirtualScreenResolutionLocked(id, virtualScreenResolution);
594 }
595
GetScreenActiveMode(ScreenId id,RSScreenModeInfo & screenModeInfo) const596 void RSScreenManager::GetScreenActiveMode(ScreenId id, RSScreenModeInfo& screenModeInfo) const
597 {
598 std::lock_guard<std::mutex> lock(mutex_);
599
600 GetScreenActiveModeLocked(id, screenModeInfo);
601 }
602
GetScreenSupportedModes(ScreenId id) const603 std::vector<RSScreenModeInfo> RSScreenManager::GetScreenSupportedModes(ScreenId id) const
604 {
605 std::lock_guard<std::mutex> lock(mutex_);
606
607 return GetScreenSupportedModesLocked(id);
608 }
609
GetScreenCapability(ScreenId id) const610 RSScreenCapability RSScreenManager::GetScreenCapability(ScreenId id) const
611 {
612 std::lock_guard<std::mutex> lock(mutex_);
613
614 return GetScreenCapabilityLocked(id);
615 }
616
GetScreenPowerStatus(ScreenId id) const617 ScreenPowerStatus RSScreenManager::GetScreenPowerStatus(ScreenId id) const
618 {
619 std::lock_guard<std::mutex> lock(mutex_);
620
621 return GetScreenPowerStatusLocked(id);
622 }
623
GetScreenData(ScreenId id) const624 RSScreenData RSScreenManager::GetScreenData(ScreenId id) const
625 {
626 std::lock_guard<std::mutex> lock(mutex_);
627 RSScreenData screenData;
628 if (screens_.count(id) == 0) {
629 RS_LOGW("RSScreenManager %s: There is no screen for id %" PRIu64 ".", __func__, id);
630 return screenData;
631 }
632 RSScreenCapability capability = GetScreenCapabilityLocked(id);
633 RSScreenModeInfo activeMode;
634 GetScreenActiveModeLocked(id, activeMode);
635 std::vector<RSScreenModeInfo> supportModes = GetScreenSupportedModesLocked(id);
636 ScreenPowerStatus powerStatus = GetScreenPowerStatusLocked(id);
637 screenData.SetCapability(capability);
638 screenData.SetActivityModeInfo(activeMode);
639 screenData.SetSupportModeInfo(supportModes);
640 screenData.SetPowerStatus(powerStatus);
641 return screenData;
642 }
643
GetScreenBacklight(ScreenId id)644 int32_t RSScreenManager::GetScreenBacklight(ScreenId id)
645 {
646 std::lock_guard<std::mutex> lock(mutex_);
647 return GetScreenBacklightLocked(id);
648 }
649
GetScreenBacklightLocked(ScreenId id) const650 int32_t RSScreenManager::GetScreenBacklightLocked(ScreenId id) const
651 {
652 if (screens_.count(id) == 0) {
653 RS_LOGW("RSScreenManager %s: There is no screen for id %" PRIu64 ".", __func__, id);
654 return INVALID_BACKLIGHT_VALUE;
655 }
656
657 int32_t level = screens_.at(id)->GetScreenBacklight();
658 return level;
659 }
660
SetScreenBacklight(ScreenId id,uint32_t level)661 void RSScreenManager::SetScreenBacklight(ScreenId id, uint32_t level)
662 {
663 std::lock_guard<std::mutex> lock(mutex_);
664 if (screens_.count(id) == 0) {
665 RS_LOGW("RSScreenManager %s: There is no screen for id %" PRIu64 ".", __func__, id);
666 return;
667 }
668 screens_.at(id)->SetScreenBacklight(level);
669 }
670
QueryScreenInfo(ScreenId id) const671 ScreenInfo RSScreenManager::QueryScreenInfo(ScreenId id) const
672 {
673 std::lock_guard<std::mutex> lock(mutex_);
674
675 ScreenInfo info;
676 if (screens_.count(id) == 0) {
677 RS_LOGW("RSScreenManager %s: There is no screen for id %" PRIu64 ".", __func__, id);
678 return info;
679 }
680
681 const auto &screen = screens_.at(id);
682 info.id = id;
683 info.width = screen->Width();
684 info.height = screen->Height();
685 (void)screen->GetScreenColorGamut(info.colorGamut);
686
687 if (!screen->IsEnable()) {
688 info.state = ScreenState::DISABLED;
689 } else if (!screen->IsVirtual()) {
690 info.state = ScreenState::HDI_OUTPUT_ENABLE;
691 } else {
692 info.state = ScreenState::PRODUCER_SURFACE_ENABLE;
693 }
694 info.skipFrameInterval = screen->GetScreenSkipFrameInterval();
695
696 return info;
697 }
698
GetProducerSurface(ScreenId id) const699 sptr<Surface> RSScreenManager::GetProducerSurface(ScreenId id) const
700 {
701 std::lock_guard<std::mutex> lock(mutex_);
702
703 // assert screens_.count(id) == 1
704 if (screens_.count(id) == 0) {
705 RS_LOGW("RSScreenManager::GetProducerSurface: There is no screen for id %" PRIu64 ".", id);
706 return nullptr;
707 }
708 return screens_.at(id)->GetProducerSurface();
709 }
710
GetOutput(ScreenId id) const711 std::shared_ptr<HdiOutput> RSScreenManager::GetOutput(ScreenId id) const
712 {
713 std::lock_guard<std::mutex> lock(mutex_);
714
715 // assert screens_.count(id) == 1
716 if (screens_.count(id) == 0) {
717 RS_LOGW("RSScreenManager::GetOutput: There is no screen for id %" PRIu64 ".", id);
718 return nullptr;
719 }
720 return screens_.at(id)->GetOutput();
721 }
722
AddScreenChangeCallback(const sptr<RSIScreenChangeCallback> & callback)723 int32_t RSScreenManager::AddScreenChangeCallback(const sptr<RSIScreenChangeCallback> &callback)
724 {
725 if (callback == nullptr) {
726 RS_LOGE("RSScreenManager %s: callback is NULL.", __func__);
727 return INVALID_ARGUMENTS;
728 }
729
730 std::lock_guard<std::mutex> lock(mutex_);
731 // when the callback first registered, maybe there were some physical screens already connected,
732 // so notify to remote immediately.
733 for (const auto &[id, screen] : screens_) {
734 if (!screen->IsVirtual()) {
735 callback->OnScreenChanged(id, ScreenEvent::CONNECTED);
736 }
737 }
738 screenChangeCallbacks_.push_back(callback);
739 RS_LOGD("RSScreenManager %s: add a remote callback succeed.", __func__);
740 return SUCCESS;
741 }
742
RemoveScreenChangeCallback(const sptr<RSIScreenChangeCallback> & callback)743 void RSScreenManager::RemoveScreenChangeCallback(const sptr<RSIScreenChangeCallback> &callback)
744 {
745 std::lock_guard<std::mutex> lock(mutex_);
746 for (auto it = screenChangeCallbacks_.begin(); it != screenChangeCallbacks_.end(); it++) {
747 if (*it == callback) {
748 screenChangeCallbacks_.erase(it);
749 RS_LOGD("RSScreenManager %s: remove a remote callback succeed.", __func__);
750 break;
751 }
752 }
753 }
754
DisplayDump(std::string & dumpString)755 void RSScreenManager::DisplayDump(std::string& dumpString)
756 {
757 int32_t index = 0;
758 for (const auto &[id, screen] : screens_) {
759 screen->DisplayDump(index, dumpString);
760 index++;
761 }
762 }
763
SurfaceDump(std::string & dumpString)764 void RSScreenManager::SurfaceDump(std::string& dumpString)
765 {
766 int32_t index = 0;
767 for (const auto &[id, screen] : screens_) {
768 screen->SurfaceDump(index, dumpString);
769 index++;
770 }
771 }
772
FpsDump(std::string & dumpString,std::string & arg)773 void RSScreenManager::FpsDump(std::string& dumpString, std::string& arg)
774 {
775 int32_t index = 0;
776 dumpString += "\n-- The recently fps records info of screens:\n";
777 for (const auto &[id, screen] : screens_) {
778 screen->FpsDump(index, dumpString, arg);
779 index++;
780 }
781 }
782
ClearFpsDump(std::string & dumpString,std::string & arg)783 void RSScreenManager::ClearFpsDump(std::string& dumpString, std::string& arg)
784 {
785 int32_t index = 0;
786 dumpString += "\n-- Clear fps records info of screens:\n";
787 for (const auto &[id, screen] : screens_) {
788 screen->ClearFpsDump(index, dumpString, arg);
789 index++;
790 }
791 }
792
GetScreenSupportedColorGamutsLocked(ScreenId id,std::vector<ScreenColorGamut> & mode) const793 int32_t RSScreenManager::GetScreenSupportedColorGamutsLocked(ScreenId id, std::vector<ScreenColorGamut>& mode) const
794 {
795 if (screens_.count(id) == 0) {
796 RS_LOGW("RSScreenManager %s: There is no screen for id %" PRIu64 ".", __func__, id);
797 return StatusCode::SCREEN_NOT_FOUND;
798 }
799 return screens_.at(id)->GetScreenSupportedColorGamuts(mode);
800 }
801
GetScreenSupportedMetaDataKeysLocked(ScreenId id,std::vector<ScreenHDRMetadataKey> & keys) const802 int32_t RSScreenManager::GetScreenSupportedMetaDataKeysLocked(
803 ScreenId id, std::vector<ScreenHDRMetadataKey>& keys) const
804 {
805 if (screens_.count(id) == 0) {
806 RS_LOGW("RSScreenManager %s: There is no screen for id %" PRIu64 ".", __func__, id);
807 return StatusCode::SCREEN_NOT_FOUND;
808 }
809 return screens_.at(id)->GetScreenSupportedMetaDataKeys(keys);
810 }
811
GetScreenColorGamutLocked(ScreenId id,ScreenColorGamut & mode) const812 int32_t RSScreenManager::GetScreenColorGamutLocked(ScreenId id, ScreenColorGamut& mode) const
813 {
814 if (screens_.count(id) == 0) {
815 RS_LOGW("RSScreenManager %s: There is no screen for id %" PRIu64 ".", __func__, id);
816 return StatusCode::SCREEN_NOT_FOUND;
817 }
818 return screens_.at(id)->GetScreenColorGamut(mode);
819 }
820
SetScreenColorGamutLocked(ScreenId id,int32_t modeIdx)821 int32_t RSScreenManager::SetScreenColorGamutLocked(ScreenId id, int32_t modeIdx)
822 {
823 if (screens_.count(id) == 0) {
824 RS_LOGW("RSScreenManager %s: There is no screen for id %" PRIu64 ".", __func__, id);
825 return StatusCode::SCREEN_NOT_FOUND;
826 }
827 return screens_.at(id)->SetScreenColorGamut(modeIdx);
828 }
829
SetScreenGamutMapLocked(ScreenId id,ScreenGamutMap mode)830 int32_t RSScreenManager::SetScreenGamutMapLocked(ScreenId id, ScreenGamutMap mode)
831 {
832 if (screens_.count(id) == 0) {
833 RS_LOGW("RSScreenManager %s: There is no screen for id %" PRIu64 ".", __func__, id);
834 return StatusCode::SCREEN_NOT_FOUND;
835 }
836 return screens_.at(id)->SetScreenGamutMap(mode);
837 }
838
GetScreenGamutMapLocked(ScreenId id,ScreenGamutMap & mode) const839 int32_t RSScreenManager::GetScreenGamutMapLocked(ScreenId id, ScreenGamutMap &mode) const
840 {
841 if (screens_.count(id) == 0) {
842 RS_LOGW("RSScreenManager %s: There is no screen for id %" PRIu64 ".", __func__, id);
843 return StatusCode::SCREEN_NOT_FOUND;
844 }
845 return screens_.at(id)->GetScreenGamutMap(mode);
846 }
847
GetScreenHDRCapabilityLocked(ScreenId id,RSScreenHDRCapability & screenHdrCapability) const848 int32_t RSScreenManager::GetScreenHDRCapabilityLocked(ScreenId id, RSScreenHDRCapability& screenHdrCapability) const
849 {
850 if (screens_.count(id) == 0) {
851 RS_LOGW("RSScreenManager %s: There is no screen for id %" PRIu64 ".", __func__, id);
852 return StatusCode::SCREEN_NOT_FOUND;
853 }
854 HDRCapability hdrCapability = screens_.at(id)->GetHDRCapability();
855 std::vector<ScreenHDRFormat> hdrFormats;
856 uint32_t formatCount = hdrCapability.formatCount;
857 hdrFormats.resize(formatCount);
858 for (uint32_t index = 0; index < formatCount; index++) {
859 hdrFormats[index] = static_cast<ScreenHDRFormat>(hdrCapability.formats[index]);
860 }
861 screenHdrCapability.SetMaxLum(hdrCapability.maxLum);
862 screenHdrCapability.SetMaxAverageLum(hdrCapability.maxAverageLum);
863 screenHdrCapability.SetMinLum(hdrCapability.minLum);
864 screenHdrCapability.SetHdrFormats(hdrFormats);
865 return StatusCode::SUCCESS;
866 }
867
GetScreenTypeLocked(ScreenId id,RSScreenType & type) const868 int32_t RSScreenManager::GetScreenTypeLocked(ScreenId id, RSScreenType& type) const
869 {
870 if (screens_.count(id) == 0) {
871 RS_LOGW("RSScreenManager %s: There is no screen for id %" PRIu64 ".", __func__, id);
872 return StatusCode::SCREEN_NOT_FOUND;
873 }
874
875 type = screens_.at(id)->GetScreenType();
876 return StatusCode::SUCCESS;
877 }
878
SetScreenSkipFrameIntervalLocked(ScreenId id,uint32_t skipFrameInterval)879 int32_t RSScreenManager::SetScreenSkipFrameIntervalLocked(ScreenId id, uint32_t skipFrameInterval)
880 {
881 if (screens_.count(id) == 0) {
882 RS_LOGW("RSScreenManager %s: There is no screen for id %" PRIu64 ".", __func__, id);
883 return StatusCode::SCREEN_NOT_FOUND;
884 }
885 RSScreenModeInfo screenModeInfo;
886 // use the refresh rate of the physical screen as the maximum refresh rate
887 GetScreenActiveModeLocked(defaultScreenId_, screenModeInfo);
888 // guaranteed screen refresh rate at least 1
889 if (skipFrameInterval == 0 || (skipFrameInterval > screenModeInfo.GetScreenRefreshRate())) {
890 return INVALID_ARGUMENTS;
891 }
892 screens_.at(id)->SetScreenSkipFrameInterval(skipFrameInterval);
893 RS_LOGD("RSScreenManager %s: screen(id %" PRIu64 "), skipFrameInterval(%d).",
894 __func__, id, skipFrameInterval);
895 return StatusCode::SUCCESS;
896 }
897
GetScreenSupportedColorGamuts(ScreenId id,std::vector<ScreenColorGamut> & mode) const898 int32_t RSScreenManager::GetScreenSupportedColorGamuts(ScreenId id, std::vector<ScreenColorGamut>& mode) const
899 {
900 std::lock_guard<std::mutex> lock(mutex_);
901 return GetScreenSupportedColorGamutsLocked(id, mode);
902 }
903
GetScreenSupportedMetaDataKeys(ScreenId id,std::vector<ScreenHDRMetadataKey> & keys) const904 int32_t RSScreenManager::GetScreenSupportedMetaDataKeys(ScreenId id, std::vector<ScreenHDRMetadataKey>& keys) const
905 {
906 std::lock_guard<std::mutex> lock(mutex_);
907 return GetScreenSupportedMetaDataKeysLocked(id, keys);
908 }
909
GetScreenColorGamut(ScreenId id,ScreenColorGamut & mode) const910 int32_t RSScreenManager::GetScreenColorGamut(ScreenId id, ScreenColorGamut &mode) const
911 {
912 std::lock_guard<std::mutex> lock(mutex_);
913 return GetScreenColorGamutLocked(id, mode);
914 }
915
SetScreenColorGamut(ScreenId id,int32_t modeIdx)916 int32_t RSScreenManager::SetScreenColorGamut(ScreenId id, int32_t modeIdx)
917 {
918 std::lock_guard<std::mutex> lock(mutex_);
919 return SetScreenColorGamutLocked(id, modeIdx);
920 }
921
SetScreenGamutMap(ScreenId id,ScreenGamutMap mode)922 int32_t RSScreenManager::SetScreenGamutMap(ScreenId id, ScreenGamutMap mode)
923 {
924 std::lock_guard<std::mutex> lock(mutex_);
925 return SetScreenGamutMapLocked(id, mode);
926 }
927
GetScreenGamutMap(ScreenId id,ScreenGamutMap & mode) const928 int32_t RSScreenManager::GetScreenGamutMap(ScreenId id, ScreenGamutMap &mode) const
929 {
930 std::lock_guard<std::mutex> lock(mutex_);
931 return GetScreenGamutMapLocked(id, mode);
932 }
933
GetScreenHDRCapability(ScreenId id,RSScreenHDRCapability & screenHdrCapability) const934 int32_t RSScreenManager::GetScreenHDRCapability(ScreenId id, RSScreenHDRCapability& screenHdrCapability) const
935 {
936 std::lock_guard<std::mutex> lock(mutex_);
937 return GetScreenHDRCapabilityLocked(id, screenHdrCapability);
938 }
939
GetScreenType(ScreenId id,RSScreenType & type) const940 int32_t RSScreenManager::GetScreenType(ScreenId id, RSScreenType& type) const
941 {
942 std::lock_guard<std::mutex> lock(mutex_);
943 return GetScreenTypeLocked(id, type);
944 }
945
SetScreenSkipFrameInterval(ScreenId id,uint32_t skipFrameInterval)946 int32_t RSScreenManager::SetScreenSkipFrameInterval(ScreenId id, uint32_t skipFrameInterval)
947 {
948 std::lock_guard<std::mutex> lock(mutex_);
949 return SetScreenSkipFrameIntervalLocked(id, skipFrameInterval);
950 }
951 } // namespace impl
952
CreateOrGetScreenManager()953 sptr<RSScreenManager> CreateOrGetScreenManager()
954 {
955 return impl::RSScreenManager::GetInstance();
956 }
957 } // namespace Rosen
958 } // namespace OHOS
959