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,ScreenId & screenGroupId)61 DMError MultiScreenManager::VirtualScreenMirrorSwitch(const ScreenId mainScreenId,
62 const std::vector<ScreenId>& screenIds, 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);
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)87 DMError MultiScreenManager::PhysicalScreenMirrorSwitch(const std::vector<ScreenId>& screenIds)
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 (displayNode != nullptr) {
106 displayNode->RemoveFromTree();
107 }
108 screenSession->ReleaseDisplayNode();
109 RSDisplayNodeConfig config = { screenSession->screenId_, true, nodeId, true };
110 screenSession->CreateDisplayNode(config);
111 }
112 TLOGI(WmsLogTag::DMS, "physical screen switch to mirror end");
113 HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:PhysicalScreenMirrorSwitch end");
114 return DMError::DM_OK;
115 }
116
PhysicalScreenUniqueSwitch(const std::vector<ScreenId> & screenIds)117 DMError MultiScreenManager::PhysicalScreenUniqueSwitch(const std::vector<ScreenId>& screenIds)
118 {
119 TLOGI(WmsLogTag::DMS, "enter physical screen unique switch screen size: %{public}u",
120 static_cast<uint32_t>(screenIds.size()));
121 HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:PhysicalScreenUniqueSwitch start");
122 for (ScreenId physicalScreenId : screenIds) {
123 auto screenSession = ScreenSessionManager::GetInstance().GetScreenSession(physicalScreenId);
124 if (screenSession == nullptr) {
125 continue;
126 }
127 TLOGI(WmsLogTag::DMS, "switch to unique physical ScreenId: %{public}" PRIu64, physicalScreenId);
128 std::shared_ptr<RSDisplayNode> displayNode = screenSession->GetDisplayNode();
129 if (displayNode != nullptr) {
130 displayNode->RemoveFromTree();
131 }
132 screenSession->ReleaseDisplayNode();
133 RSDisplayNodeConfig config = { screenSession->screenId_ };
134 screenSession->CreateDisplayNode(config);
135 ScreenSessionManager::GetInstance().OnVirtualScreenChange(physicalScreenId, ScreenEvent::CONNECTED);
136 }
137 TLOGI(WmsLogTag::DMS, "physical screen unique switch end");
138 HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:PhysicalScreenUniqueSwitch end");
139 return DMError::DM_OK;
140 }
141
VirtualScreenUniqueSwitch(sptr<ScreenSession> screenSession,const std::vector<ScreenId> & screenIds)142 DMError MultiScreenManager::VirtualScreenUniqueSwitch(sptr<ScreenSession> screenSession,
143 const std::vector<ScreenId>& screenIds)
144 {
145 if (screenSession == nullptr) {
146 TLOGE(WmsLogTag::DMS, "screenSession is null");
147 return DMError::DM_ERROR_NULLPTR;
148 }
149 HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:VirtualScreenUniqueSwitch start");
150 TLOGI(WmsLogTag::DMS, "start virtual screen unique switch size: %{public}u",
151 static_cast<uint32_t>(screenIds.size()));
152 auto group = ScreenSessionManager::GetInstance().GetAbstractScreenGroup(screenSession->groupSmsId_);
153 if (group == nullptr) {
154 group = ScreenSessionManager::GetInstance().AddToGroupLocked(screenSession, true);
155 if (group == nullptr) {
156 TLOGE(WmsLogTag::DMS, "group is nullptr");
157 return DMError::DM_ERROR_NULLPTR;
158 }
159 ScreenSessionManager::GetInstance().NotifyScreenGroupChanged(screenSession->ConvertToScreenInfo(),
160 ScreenGroupChangeEvent::ADD_TO_GROUP);
161 }
162 Point point;
163 std::vector<Point> startPoints;
164 startPoints.insert(startPoints.begin(), screenIds.size(), point);
165 ScreenSessionManager::GetInstance().ChangeScreenGroup(group, screenIds, startPoints,
166 true, ScreenCombination::SCREEN_UNIQUE);
167
168 for (ScreenId uniqueScreenId : screenIds) {
169 auto uniqueScreen = ScreenSessionManager::GetInstance().GetScreenSession(uniqueScreenId);
170 if (uniqueScreen != nullptr) {
171 uniqueScreen->SetScreenCombination(ScreenCombination::SCREEN_UNIQUE);
172 ScreenSessionManager::GetInstance().NotifyScreenChanged(uniqueScreen->ConvertToScreenInfo(),
173 ScreenChangeEvent::SCREEN_SWITCH_CHANGE);
174 }
175 // virtual screen create callback to notify scb
176 ScreenSessionManager::GetInstance().OnVirtualScreenChange(uniqueScreenId, ScreenEvent::CONNECTED);
177 }
178 HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:VirtualScreenUniqueSwitch end");
179 TLOGI(WmsLogTag::DMS, "virtual screen switch to unique and notify scb end");
180 return DMError::DM_OK;
181 }
182
UniqueSwitch(const std::vector<ScreenId> & screenIds)183 DMError MultiScreenManager::UniqueSwitch(const std::vector<ScreenId>& screenIds)
184 {
185 DMError switchStatus = DMError::DM_OK;
186 std::vector<ScreenId> virtualScreenIds;
187 std::vector<ScreenId> physicalScreenIds;
188 if (screenIds.empty()) {
189 TLOGI(WmsLogTag::DMS, "mirror to unique switch screen size empty");
190 return switchStatus;
191 }
192 TLOGI(WmsLogTag::DMS, "enter mirror to unique switch screen size: %{public}u",
193 static_cast<uint32_t>(screenIds.size()));
194 FilterPhysicalAndVirtualScreen(screenIds, physicalScreenIds, virtualScreenIds);
195
196 if (!virtualScreenIds.empty()) {
197 switchStatus = ScreenSessionManager::GetInstance().VirtualScreenUniqueSwitch(virtualScreenIds);
198 TLOGI(WmsLogTag::DMS, "virtual screen switch to unique result: %{public}d", switchStatus);
199 }
200 if (!physicalScreenIds.empty()) {
201 switchStatus = PhysicalScreenUniqueSwitch(physicalScreenIds);
202 TLOGI(WmsLogTag::DMS, "physical screen switch to unique result: %{public}d", switchStatus);
203 }
204 TLOGI(WmsLogTag::DMS, "mirror switch to unique end");
205 return switchStatus;
206 }
207
MirrorSwitch(const ScreenId mainScreenId,const std::vector<ScreenId> & screenIds,ScreenId & screenGroupId)208 DMError MultiScreenManager::MirrorSwitch(const ScreenId mainScreenId, const std::vector<ScreenId>& screenIds,
209 ScreenId& screenGroupId)
210 {
211 DMError switchStatus = DMError::DM_OK;
212 std::vector<ScreenId> virtualScreenIds;
213 std::vector<ScreenId> physicalScreenIds;
214 if (screenIds.empty()) {
215 TLOGI(WmsLogTag::DMS, "mirror switch screen size empty");
216 return switchStatus;
217 }
218 TLOGI(WmsLogTag::DMS, "enter mirror switch screen size: %{public}u", static_cast<uint32_t>(screenIds.size()));
219 FilterPhysicalAndVirtualScreen(screenIds, physicalScreenIds, virtualScreenIds);
220
221 if (!virtualScreenIds.empty()) {
222 switchStatus = VirtualScreenMirrorSwitch(mainScreenId, virtualScreenIds, screenGroupId);
223 TLOGI(WmsLogTag::DMS, "virtual screen switch to mirror result: %{public}d", switchStatus);
224 }
225 if (!physicalScreenIds.empty()) {
226 screenGroupId = 1;
227 switchStatus = PhysicalScreenMirrorSwitch(physicalScreenIds);
228 TLOGI(WmsLogTag::DMS, "physical screen switch to mirror result: %{public}d", switchStatus);
229 }
230 TLOGI(WmsLogTag::DMS, "mirror switch end switchStatus: %{public}d", switchStatus);
231 return switchStatus;
232 }
233 } // namespace OHOS::Rosen