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