• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 "multi_screen_manager.h"
17 
18 namespace OHOS::Rosen {
WM_IMPLEMENT_SINGLE_INSTANCE(MultiScreenManager)19 WM_IMPLEMENT_SINGLE_INSTANCE(MultiScreenManager)
20 
21 MultiScreenManager::MultiScreenManager()
22 {
23     TLOGI(WmsLogTag::DMS, "init multi screen manager");
24 }
25 
~MultiScreenManager()26 MultiScreenManager::~MultiScreenManager()
27 {
28     TLOGI(WmsLogTag::DMS, "destructor multi screen manager");
29 }
30 
FilterPhysicalAndVirtualScreen(const std::vector<ScreenId> & allScreenIds,std::vector<ScreenId> & physicalScreenIds,std::vector<ScreenId> & virtualScreenIds)31 void MultiScreenManager::FilterPhysicalAndVirtualScreen(const std::vector<ScreenId>& allScreenIds,
32     std::vector<ScreenId>& physicalScreenIds, std::vector<ScreenId>& virtualScreenIds)
33 {
34     TLOGI(WmsLogTag::DMS, "filter physical and virtual screen enter allScreen size: %{public}u",
35         static_cast<uint32_t>(allScreenIds.size()));
36     sptr<ScreenSession> defaultSession = ScreenSessionManager::GetInstance().GetDefaultScreenSession();
37     if (defaultSession == nullptr) {
38         TLOGE(WmsLogTag::DMS, "fail to get defaultSession");
39         return;
40     }
41     ScreenId defaultScreenId = defaultSession->GetScreenId();
42     for (ScreenId screenId : allScreenIds) {
43         auto screenSession = ScreenSessionManager::GetInstance().GetScreenSession(screenId);
44         if (screenSession == nullptr) {
45             continue;
46         }
47         if (screenSession->GetScreenId() == defaultScreenId) {
48             continue;
49         }
50         if (screenSession->GetMirrorScreenType() == MirrorScreenType::PHYSICAL_MIRROR) {
51             physicalScreenIds.emplace_back(screenId);
52         } else if (screenSession->GetMirrorScreenType() == MirrorScreenType::VIRTUAL_MIRROR) {
53             virtualScreenIds.emplace_back(screenId);
54         } else {
55             TLOGI(WmsLogTag::DMS, "mirror screen type error");
56         }
57     }
58     TLOGI(WmsLogTag::DMS, "filter physical and virtual screen end");
59 }
60 
VirtualScreenMirrorSwitch(const ScreenId mainScreenId,const std::vector<ScreenId> & screenIds,DMRect mainScreenRegion,ScreenId & screenGroupId)61 DMError MultiScreenManager::VirtualScreenMirrorSwitch(const ScreenId mainScreenId,
62     const std::vector<ScreenId>& screenIds, DMRect mainScreenRegion, ScreenId& screenGroupId)
63 {
64     TLOGI(WmsLogTag::DMS, "virtual screen mirror switch enter size: %{public}u",
65         static_cast<uint32_t>(screenIds.size()));
66     HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:VirtualScreenMirrorSwitch start");
67     auto mainScreen = ScreenSessionManager::GetInstance().GetScreenSession(mainScreenId);
68     if (mainScreen == nullptr) {
69         TLOGE(WmsLogTag::DMS, "screen session null fail mainScreenId: %{public}" PRIu64, mainScreenId);
70         return DMError::DM_ERROR_INVALID_PARAM;
71     }
72     DMError ret = ScreenSessionManager::GetInstance().SetMirror(mainScreenId, screenIds, mainScreenRegion);
73     if (ret != DMError::DM_OK) {
74         TLOGE(WmsLogTag::DMS, "virtual screen mirror switch error: %{public}d", ret);
75         return ret;
76     }
77     if (ScreenSessionManager::GetInstance().GetAbstractScreenGroup(mainScreen->groupSmsId_) == nullptr) {
78         TLOGE(WmsLogTag::DMS, "get screen group failed main screenId: %{public}" PRIu64, mainScreenId);
79         return DMError::DM_ERROR_NULLPTR;
80     }
81     screenGroupId = mainScreen->groupSmsId_;
82     TLOGI(WmsLogTag::DMS, "virtual screen mirror switch end");
83     HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:VirtualScreenMirrorSwitch end");
84     return ret;
85 }
86 
PhysicalScreenMirrorSwitch(const std::vector<ScreenId> & screenIds,DMRect mirrorRegion)87 DMError MultiScreenManager::PhysicalScreenMirrorSwitch(const std::vector<ScreenId>& screenIds, DMRect mirrorRegion)
88 {
89     sptr<ScreenSession> defaultSession = ScreenSessionManager::GetInstance().GetDefaultScreenSession();
90     if (defaultSession == nullptr) {
91         TLOGE(WmsLogTag::DMS, "fail to get defaultSession");
92         return DMError::DM_ERROR_NULLPTR;
93     }
94     TLOGI(WmsLogTag::DMS, "enter physical screen switch to mirror screen size: %{public}u",
95         static_cast<uint32_t>(screenIds.size()));
96     HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:PhysicalScreenMirrorSwitch start");
97     NodeId nodeId = defaultSession->GetDisplayNode() == nullptr ? 0 : defaultSession->GetDisplayNode()->GetId();
98     for (ScreenId physicalScreenId : screenIds) {
99         auto screenSession = ScreenSessionManager::GetInstance().GetScreenSession(physicalScreenId);
100         if (screenSession == nullptr) {
101             continue;
102         }
103         TLOGI(WmsLogTag::DMS, "switch to mirror physical ScreenId: %{public}" PRIu64, physicalScreenId);
104         std::shared_ptr<RSDisplayNode> displayNode = screenSession->GetDisplayNode();
105         if (screenSession->GetScreenCombination() == ScreenCombination::SCREEN_MIRROR) {
106             if (mirrorRegion != screenSession->GetMirrorScreenRegion().second) {
107                 screenSession->SetMirrorScreenRegion(defaultSession->GetRSScreenId(), mirrorRegion);
108                 screenSession->SetIsPhysicalMirrorSwitch(true);
109                 screenSession->EnableMirrorScreenRegion();
110             }
111             TLOGW(WmsLogTag::DMS, "already mirror and get a same region.");
112             return DMError::DM_OK;
113         }
114         if (displayNode != nullptr) {
115             displayNode->RemoveFromTree();
116         }
117         screenSession->ReleaseDisplayNode();
118         screenSession->SetMirrorScreenRegion(defaultSession->GetRSScreenId(), mirrorRegion);
119         screenSession->SetIsPhysicalMirrorSwitch(true);
120         RSDisplayNodeConfig config = { screenSession->screenId_, true, nodeId, true };
121         screenSession->CreateDisplayNode(config);
122         screenSession->SetScreenCombination(ScreenCombination::SCREEN_MIRROR);
123     }
124     TLOGI(WmsLogTag::DMS, "physical screen switch to mirror end");
125     HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:PhysicalScreenMirrorSwitch end");
126     return DMError::DM_OK;
127 }
128 
PhysicalScreenUniqueSwitch(const std::vector<ScreenId> & screenIds)129 DMError MultiScreenManager::PhysicalScreenUniqueSwitch(const std::vector<ScreenId>& screenIds)
130 {
131     TLOGI(WmsLogTag::DMS, "enter physical screen unique switch screen size: %{public}u",
132         static_cast<uint32_t>(screenIds.size()));
133     HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:PhysicalScreenUniqueSwitch start");
134     for (ScreenId physicalScreenId : screenIds) {
135         auto screenSession = ScreenSessionManager::GetInstance().GetScreenSession(physicalScreenId);
136         if (screenSession == nullptr) {
137             continue;
138         }
139         TLOGI(WmsLogTag::DMS, "switch to unique physical ScreenId: %{public}" PRIu64, physicalScreenId);
140         std::shared_ptr<RSDisplayNode> displayNode = screenSession->GetDisplayNode();
141         if (displayNode != nullptr) {
142             displayNode->RemoveFromTree();
143         }
144         screenSession->ReleaseDisplayNode();
145         RSDisplayNodeConfig config = { screenSession->screenId_ };
146         screenSession->CreateDisplayNode(config);
147         ScreenSessionManager::GetInstance().OnVirtualScreenChange(physicalScreenId, ScreenEvent::CONNECTED);
148     }
149     TLOGI(WmsLogTag::DMS, "physical screen unique switch end");
150     HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:PhysicalScreenUniqueSwitch end");
151     return DMError::DM_OK;
152 }
153 
VirtualScreenUniqueSwitch(sptr<ScreenSession> screenSession,const std::vector<ScreenId> & screenIds)154 DMError MultiScreenManager::VirtualScreenUniqueSwitch(sptr<ScreenSession> screenSession,
155     const std::vector<ScreenId>& screenIds)
156 {
157     if (screenSession == nullptr) {
158         TLOGE(WmsLogTag::DMS, "screenSession is null");
159         return DMError::DM_ERROR_NULLPTR;
160     }
161     HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:VirtualScreenUniqueSwitch start");
162     TLOGI(WmsLogTag::DMS, "start virtual screen unique switch size: %{public}u",
163         static_cast<uint32_t>(screenIds.size()));
164     auto group = ScreenSessionManager::GetInstance().GetAbstractScreenGroup(screenSession->groupSmsId_);
165     if (group == nullptr) {
166         group = ScreenSessionManager::GetInstance().AddToGroupLocked(screenSession, true);
167         if (group == nullptr) {
168             TLOGE(WmsLogTag::DMS, "group is nullptr");
169             return DMError::DM_ERROR_NULLPTR;
170         }
171         ScreenSessionManager::GetInstance().NotifyScreenGroupChanged(screenSession->ConvertToScreenInfo(),
172             ScreenGroupChangeEvent::ADD_TO_GROUP);
173     }
174     Point point;
175     std::vector<Point> startPoints;
176     startPoints.insert(startPoints.begin(), screenIds.size(), point);
177     ScreenSessionManager::GetInstance().ChangeScreenGroup(group, screenIds, startPoints,
178         true, ScreenCombination::SCREEN_UNIQUE);
179 
180     for (ScreenId uniqueScreenId : screenIds) {
181         auto uniqueScreen = ScreenSessionManager::GetInstance().GetScreenSession(uniqueScreenId);
182         if (uniqueScreen != nullptr) {
183             uniqueScreen->SetScreenCombination(ScreenCombination::SCREEN_UNIQUE);
184             ScreenSessionManager::GetInstance().NotifyScreenChanged(uniqueScreen->ConvertToScreenInfo(),
185                 ScreenChangeEvent::SCREEN_SWITCH_CHANGE);
186         }
187         // virtual screen create callback to notify scb
188         ScreenSessionManager::GetInstance().OnVirtualScreenChange(uniqueScreenId, ScreenEvent::CONNECTED);
189     }
190     HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:VirtualScreenUniqueSwitch end");
191     TLOGI(WmsLogTag::DMS, "virtual screen switch to unique and notify scb end");
192     return DMError::DM_OK;
193 }
194 
UniqueSwitch(const std::vector<ScreenId> & screenIds)195 DMError MultiScreenManager::UniqueSwitch(const std::vector<ScreenId>& screenIds)
196 {
197     DMError switchStatus = DMError::DM_OK;
198     std::vector<ScreenId> virtualScreenIds;
199     std::vector<ScreenId> physicalScreenIds;
200     if (screenIds.empty()) {
201         TLOGI(WmsLogTag::DMS, "mirror to unique switch screen size empty");
202         return switchStatus;
203     }
204     TLOGI(WmsLogTag::DMS, "enter mirror to unique switch screen size: %{public}u",
205         static_cast<uint32_t>(screenIds.size()));
206     FilterPhysicalAndVirtualScreen(screenIds, physicalScreenIds, virtualScreenIds);
207 
208     if (!virtualScreenIds.empty()) {
209         switchStatus = ScreenSessionManager::GetInstance().VirtualScreenUniqueSwitch(virtualScreenIds);
210         TLOGI(WmsLogTag::DMS, "virtual screen switch to unique result: %{public}d", switchStatus);
211     }
212     if (!physicalScreenIds.empty()) {
213         switchStatus = PhysicalScreenUniqueSwitch(physicalScreenIds);
214         TLOGI(WmsLogTag::DMS, "physical screen switch to unique result: %{public}d", switchStatus);
215     }
216     TLOGI(WmsLogTag::DMS, "mirror switch to unique end");
217     return switchStatus;
218 }
219 
MirrorSwitch(const ScreenId mainScreenId,const std::vector<ScreenId> & screenIds,DMRect mainScreenRegion,ScreenId & screenGroupId)220 DMError MultiScreenManager::MirrorSwitch(const ScreenId mainScreenId, const std::vector<ScreenId>& screenIds,
221     DMRect mainScreenRegion, ScreenId& screenGroupId)
222 {
223     DMError switchStatus = DMError::DM_OK;
224     std::vector<ScreenId> virtualScreenIds;
225     std::vector<ScreenId> physicalScreenIds;
226     if (screenIds.empty()) {
227         TLOGI(WmsLogTag::DMS, "mirror switch screen size empty");
228         return switchStatus;
229     }
230     TLOGI(WmsLogTag::DMS, "enter mirror switch screen size: %{public}u", static_cast<uint32_t>(screenIds.size()));
231     FilterPhysicalAndVirtualScreen(screenIds, physicalScreenIds, virtualScreenIds);
232 
233     if (!virtualScreenIds.empty()) {
234         switchStatus = VirtualScreenMirrorSwitch(mainScreenId, virtualScreenIds, mainScreenRegion, screenGroupId);
235         TLOGI(WmsLogTag::DMS, "virtual screen switch to mirror result: %{public}d", switchStatus);
236     }
237     if (!physicalScreenIds.empty()) {
238         screenGroupId = 1;
239         switchStatus = PhysicalScreenMirrorSwitch(physicalScreenIds, mainScreenRegion);
240         TLOGI(WmsLogTag::DMS, "physical screen switch to mirror result: %{public}d", switchStatus);
241     }
242     TLOGI(WmsLogTag::DMS, "mirror switch end switchStatus: %{public}d", switchStatus);
243     return switchStatus;
244 }
245 } // namespace OHOS::Rosen