• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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