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 #include "screen_power_utils.h"
18 #include "screen_scene_config.h"
19 #ifdef RES_SCHED_ENABLE
20 #include "res_sched_client.h"
21 #include "res_type.h"
22 #endif
23
24 namespace OHOS::Rosen {
25 WM_IMPLEMENT_SINGLE_INSTANCE(MultiScreenManager)
26 namespace {
27 const std::string SCREEN_EXTEND = "extend";
28 const std::string SCREEN_MIRROR = "mirror";
29 const std::string MULTI_SCREEN_EXIT_STR = "exit";
30 const std::string MULTI_SCREEN_ENTER_STR = "enter";
31 constexpr int32_t MULTI_SCREEN_EXIT = 0;
32 constexpr int32_t MULTI_SCREEN_ENTER = 1;
33 }
MultiScreenManager()34 MultiScreenManager::MultiScreenManager()
35 {
36 TLOGI(WmsLogTag::DMS, "init");
37 lastScreenMode_ = std::make_pair(SCREEN_ID_INVALID, MultiScreenMode::SCREEN_MIRROR);
38 }
39
~MultiScreenManager()40 MultiScreenManager::~MultiScreenManager()
41 {
42 TLOGI(WmsLogTag::DMS, "destructor");
43 }
44
FilterPhysicalAndVirtualScreen(const std::vector<ScreenId> & allScreenIds,std::vector<ScreenId> & physicalScreenIds,std::vector<ScreenId> & virtualScreenIds)45 void MultiScreenManager::FilterPhysicalAndVirtualScreen(const std::vector<ScreenId>& allScreenIds,
46 std::vector<ScreenId>& physicalScreenIds, std::vector<ScreenId>& virtualScreenIds)
47 {
48 TLOGW(WmsLogTag::DMS, "enter allScreen size: %{public}u",
49 static_cast<uint32_t>(allScreenIds.size()));
50 sptr<ScreenSession> defaultSession = ScreenSessionManager::GetInstance().GetDefaultScreenSession();
51 if (defaultSession == nullptr) {
52 TLOGE(WmsLogTag::DMS, "fail to get defaultSession");
53 return;
54 }
55 ScreenId defaultScreenId = defaultSession->GetScreenId();
56 for (ScreenId screenId : allScreenIds) {
57 auto screenSession = ScreenSessionManager::GetInstance().GetScreenSession(screenId);
58 if (screenSession == nullptr) {
59 continue;
60 }
61 if (screenSession->GetScreenId() == defaultScreenId) {
62 continue;
63 }
64 if (screenSession->GetMirrorScreenType() == MirrorScreenType::PHYSICAL_MIRROR) {
65 physicalScreenIds.emplace_back(screenId);
66 } else if (screenSession->GetMirrorScreenType() == MirrorScreenType::VIRTUAL_MIRROR) {
67 virtualScreenIds.emplace_back(screenId);
68 } else {
69 TLOGW(WmsLogTag::DMS, "mirror screen type error");
70 }
71 }
72 TLOGW(WmsLogTag::DMS, "end");
73 }
74
VirtualScreenMirrorSwitch(const ScreenId mainScreenId,const std::vector<ScreenId> & screenIds,DMRect mainScreenRegion,ScreenId & screenGroupId)75 DMError MultiScreenManager::VirtualScreenMirrorSwitch(const ScreenId mainScreenId,
76 const std::vector<ScreenId>& screenIds, DMRect mainScreenRegion, ScreenId& screenGroupId)
77 {
78 TLOGW(WmsLogTag::DMS, "enter size: %{public}u",
79 static_cast<uint32_t>(screenIds.size()));
80 HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:VirtualScreenMirrorSwitch start");
81 auto mainScreen = ScreenSessionManager::GetInstance().GetScreenSession(mainScreenId);
82 if (mainScreen == nullptr) {
83 TLOGE(WmsLogTag::DMS, "screen session null fail mainScreenId: %{public}" PRIu64, mainScreenId);
84 return DMError::DM_ERROR_INVALID_PARAM;
85 }
86 DMError ret = ScreenSessionManager::GetInstance().SetMirror(mainScreenId, screenIds, mainScreenRegion);
87 if (ret != DMError::DM_OK) {
88 TLOGE(WmsLogTag::DMS, "error: %{public}d", ret);
89 return ret;
90 }
91 if (ScreenSessionManager::GetInstance().GetAbstractScreenGroup(mainScreen->groupSmsId_) == nullptr) {
92 TLOGE(WmsLogTag::DMS, "get screen group failed main screenId: %{public}" PRIu64, mainScreenId);
93 return DMError::DM_ERROR_NULLPTR;
94 }
95 screenGroupId = mainScreen->groupSmsId_;
96 TLOGW(WmsLogTag::DMS, "end");
97 HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:VirtualScreenMirrorSwitch end");
98 return ret;
99 }
100
PhysicalScreenMirrorSwitch(const std::vector<ScreenId> & screenIds,DMRect mirrorRegion)101 DMError MultiScreenManager::PhysicalScreenMirrorSwitch(const std::vector<ScreenId>& screenIds, DMRect mirrorRegion)
102 {
103 sptr<ScreenSession> defaultSession = ScreenSessionManager::GetInstance().GetDefaultScreenSession();
104 if (defaultSession == nullptr) {
105 TLOGE(WmsLogTag::DMS, "fail to get defaultSession");
106 return DMError::DM_ERROR_NULLPTR;
107 }
108 TLOGW(WmsLogTag::DMS, "enter physical screen switch to mirror screen size: %{public}u",
109 static_cast<uint32_t>(screenIds.size()));
110 HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:PhysicalScreenMirrorSwitch start");
111 NodeId nodeId = defaultSession->GetDisplayNode() == nullptr ? 0 : defaultSession->GetDisplayNode()->GetId();
112 for (ScreenId physicalScreenId : screenIds) {
113 auto screenSession = ScreenSessionManager::GetInstance().GetScreenSession(physicalScreenId);
114 if (screenSession == nullptr) {
115 continue;
116 }
117 TLOGW(WmsLogTag::DMS, "switch to mirror physical ScreenId: %{public}" PRIu64, physicalScreenId);
118 std::shared_ptr<RSDisplayNode> displayNode = screenSession->GetDisplayNode();
119 if (screenSession->GetScreenCombination() == ScreenCombination::SCREEN_MIRROR) {
120 if (mirrorRegion != screenSession->GetMirrorScreenRegion().second) {
121 screenSession->SetMirrorScreenRegion(defaultSession->GetRSScreenId(), mirrorRegion);
122 screenSession->SetIsPhysicalMirrorSwitch(true);
123 screenSession->EnableMirrorScreenRegion();
124 }
125 TLOGW(WmsLogTag::DMS, "already mirror and get a same region.");
126 return DMError::DM_OK;
127 }
128 if (displayNode != nullptr) {
129 displayNode->RemoveFromTree();
130 }
131 screenSession->ReleaseDisplayNode();
132 screenSession->SetMirrorScreenRegion(defaultSession->GetRSScreenId(), mirrorRegion);
133 screenSession->SetIsPhysicalMirrorSwitch(true);
134 RSDisplayNodeConfig config = { screenSession->screenId_, true, nodeId, true };
135 screenSession->CreateDisplayNode(config);
136 screenSession->SetScreenCombination(ScreenCombination::SCREEN_MIRROR);
137 }
138 TLOGW(WmsLogTag::DMS, "physical screen switch to mirror end");
139 HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:PhysicalScreenMirrorSwitch end");
140 return DMError::DM_OK;
141 }
142
PhysicalScreenUniqueSwitch(const std::vector<ScreenId> & screenIds)143 DMError MultiScreenManager::PhysicalScreenUniqueSwitch(const std::vector<ScreenId>& screenIds)
144 {
145 TLOGW(WmsLogTag::DMS, "enter screen size: %{public}u",
146 static_cast<uint32_t>(screenIds.size()));
147 HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:PhysicalScreenUniqueSwitch start");
148 for (ScreenId physicalScreenId : screenIds) {
149 auto screenSession = ScreenSessionManager::GetInstance().GetScreenSession(physicalScreenId);
150 if (screenSession == nullptr) {
151 continue;
152 }
153 TLOGW(WmsLogTag::DMS, "switch to unique physical ScreenId: %{public}" PRIu64, physicalScreenId);
154 std::shared_ptr<RSDisplayNode> displayNode = screenSession->GetDisplayNode();
155 if (displayNode != nullptr) {
156 displayNode->RemoveFromTree();
157 }
158 screenSession->ReleaseDisplayNode();
159 screenSession->SetVirtualPixelRatio(screenSession->GetScreenProperty().GetDefaultDensity());
160 RSDisplayNodeConfig config = { screenSession->screenId_ };
161 screenSession->CreateDisplayNode(config);
162 ScreenSessionManager::GetInstance().OnVirtualScreenChange(physicalScreenId, ScreenEvent::CONNECTED);
163 }
164 TLOGW(WmsLogTag::DMS, "end");
165 HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:PhysicalScreenUniqueSwitch end");
166 return DMError::DM_OK;
167 }
168
VirtualScreenUniqueSwitch(sptr<ScreenSession> screenSession,const std::vector<ScreenId> & screenIds)169 DMError MultiScreenManager::VirtualScreenUniqueSwitch(sptr<ScreenSession> screenSession,
170 const std::vector<ScreenId>& screenIds)
171 {
172 if (screenSession == nullptr) {
173 TLOGE(WmsLogTag::DMS, "screenSession is null");
174 return DMError::DM_ERROR_NULLPTR;
175 }
176 HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:VirtualScreenUniqueSwitch start");
177 TLOGW(WmsLogTag::DMS, "start size: %{public}u",
178 static_cast<uint32_t>(screenIds.size()));
179 auto group = ScreenSessionManager::GetInstance().GetAbstractScreenGroup(screenSession->groupSmsId_);
180 if (group == nullptr) {
181 group = ScreenSessionManager::GetInstance().AddToGroupLocked(screenSession, true);
182 if (group == nullptr) {
183 TLOGE(WmsLogTag::DMS, "group is nullptr");
184 return DMError::DM_ERROR_NULLPTR;
185 }
186 ScreenSessionManager::GetInstance().NotifyScreenGroupChanged(screenSession->ConvertToScreenInfo(),
187 ScreenGroupChangeEvent::ADD_TO_GROUP);
188 }
189 Point point;
190 std::vector<Point> startPoints;
191 startPoints.insert(startPoints.begin(), screenIds.size(), point);
192 ScreenSessionManager::GetInstance().ChangeScreenGroup(group, screenIds, startPoints,
193 true, ScreenCombination::SCREEN_UNIQUE);
194
195 for (ScreenId uniqueScreenId : screenIds) {
196 auto uniqueScreen = ScreenSessionManager::GetInstance().GetScreenSession(uniqueScreenId);
197 if (uniqueScreen != nullptr) {
198 uniqueScreen->SetScreenCombination(ScreenCombination::SCREEN_UNIQUE);
199 ScreenSessionManager::GetInstance().NotifyScreenChanged(uniqueScreen->ConvertToScreenInfo(),
200 ScreenChangeEvent::SCREEN_SWITCH_CHANGE);
201 }
202 // virtual screen create callback to notify scb
203 ScreenSessionManager::GetInstance().OnVirtualScreenChange(uniqueScreenId, ScreenEvent::CONNECTED);
204 }
205 HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:VirtualScreenUniqueSwitch end");
206 TLOGW(WmsLogTag::DMS, "to unique and notify scb end");
207 return DMError::DM_OK;
208 }
209
AddUniqueScreenDisplayId(std::vector<DisplayId> & displayIds,std::vector<ScreenId> & screenIds,DMError & switchStatus)210 static void AddUniqueScreenDisplayId(std::vector<DisplayId>& displayIds,
211 std::vector<ScreenId>& screenIds, DMError& switchStatus)
212 {
213 if (switchStatus == DMError::DM_OK) {
214 for (auto screenId : screenIds) {
215 displayIds.emplace_back(static_cast<uint64_t>(screenId));
216 }
217 }
218 }
219
UniqueSwitch(const std::vector<ScreenId> & screenIds,std::vector<DisplayId> & displayIds)220 DMError MultiScreenManager::UniqueSwitch(const std::vector<ScreenId>& screenIds,
221 std::vector<DisplayId>& displayIds)
222 {
223 DMError switchStatus = DMError::DM_OK;
224 std::vector<ScreenId> virtualScreenIds;
225 std::vector<ScreenId> physicalScreenIds;
226 if (screenIds.empty()) {
227 TLOGW(WmsLogTag::DMS, "mirror to screen size empty");
228 return switchStatus;
229 }
230 TLOGW(WmsLogTag::DMS, "enter mirror to screen size: %{public}u",
231 static_cast<uint32_t>(screenIds.size()));
232 FilterPhysicalAndVirtualScreen(screenIds, physicalScreenIds, virtualScreenIds);
233
234 if (!virtualScreenIds.empty()) {
235 switchStatus = ScreenSessionManager::GetInstance().VirtualScreenUniqueSwitch(virtualScreenIds);
236 TLOGW(WmsLogTag::DMS, "virtual screen switch to unique result: %{public}d", switchStatus);
237 AddUniqueScreenDisplayId(displayIds, virtualScreenIds, switchStatus);
238 }
239 if (!physicalScreenIds.empty()) {
240 switchStatus = PhysicalScreenUniqueSwitch(physicalScreenIds);
241 if (switchStatus == DMError::DM_OK) {
242 for (auto screenId : physicalScreenIds) {
243 ScreenSessionManager::GetInstance().UnregisterSettingWireCastObserver(screenId);
244 }
245 }
246 if (!ScreenSessionManager::GetInstance().HasCastEngineOrPhyMirror(physicalScreenIds) &&
247 switchStatus == DMError::DM_OK && ScreenSceneConfig::GetExternalScreenDefaultMode() != "none") {
248 ScreenPowerUtils::DisablePowerForceTimingOut();
249 }
250 TLOGW(WmsLogTag::DMS, "physical screen switch to unique result: %{public}d", switchStatus);
251 AddUniqueScreenDisplayId(displayIds, physicalScreenIds, switchStatus);
252 }
253 if (displayIds.empty()) {
254 switchStatus = DMError::DM_ERROR_INVALID_PARAM;
255 }
256 TLOGW(WmsLogTag::DMS, "mirror switch to unique end");
257 return switchStatus;
258 }
259
MirrorSwitch(const ScreenId mainScreenId,const std::vector<ScreenId> & screenIds,DMRect mainScreenRegion,ScreenId & screenGroupId)260 DMError MultiScreenManager::MirrorSwitch(const ScreenId mainScreenId, const std::vector<ScreenId>& screenIds,
261 DMRect mainScreenRegion, ScreenId& screenGroupId)
262 {
263 DMError switchStatus = DMError::DM_OK;
264 std::vector<ScreenId> virtualScreenIds;
265 std::vector<ScreenId> physicalScreenIds;
266 if (screenIds.empty()) {
267 TLOGW(WmsLogTag::DMS, "screen size empty");
268 return switchStatus;
269 }
270 TLOGW(WmsLogTag::DMS, "enter screen size: %{public}u", static_cast<uint32_t>(screenIds.size()));
271 FilterPhysicalAndVirtualScreen(screenIds, physicalScreenIds, virtualScreenIds);
272
273 if (!virtualScreenIds.empty()) {
274 switchStatus = VirtualScreenMirrorSwitch(mainScreenId, virtualScreenIds, mainScreenRegion, screenGroupId);
275 TLOGW(WmsLogTag::DMS, "virtual screen switch to mirror result: %{public}d", switchStatus);
276 }
277 if (!physicalScreenIds.empty()) {
278 screenGroupId = 1;
279 switchStatus = PhysicalScreenMirrorSwitch(physicalScreenIds, mainScreenRegion);
280 if (switchStatus == DMError::DM_OK) {
281 for (auto screenId : physicalScreenIds) {
282 auto screenSession = ScreenSessionManager::GetInstance().GetScreenSession(screenId);
283 ScreenSessionManager::GetInstance().RegisterSettingWireCastObserver(screenSession);
284 }
285 // switchStatus is DM_OK and device is not PC
286 if (ScreenSceneConfig::GetExternalScreenDefaultMode() != "none") {
287 ScreenPowerUtils::EnablePowerForceTimingOut();
288 ScreenSessionManager::GetInstance().DisablePowerOffRenderControl(0);
289 }
290 }
291 TLOGW(WmsLogTag::DMS, "physical screen switch to mirror result: %{public}d", switchStatus);
292 }
293 TLOGW(WmsLogTag::DMS, "end switchStatus: %{public}d", switchStatus);
294 return switchStatus;
295 }
296
MultiScreenModeChange(sptr<ScreenSession> firstSession,sptr<ScreenSession> secondarySession,const std::string & operateType)297 void MultiScreenManager::MultiScreenModeChange(sptr<ScreenSession> firstSession, sptr<ScreenSession> secondarySession,
298 const std::string& operateType)
299 {
300 TLOGW(WmsLogTag::DMS, "enter operateType=%{public}s", operateType.c_str());
301 if (firstSession == nullptr || secondarySession == nullptr) {
302 TLOGE(WmsLogTag::DMS, "params null.");
303 return;
304 }
305 ScreenCombination firstCombination = firstSession->GetScreenCombination();
306 if (firstCombination == ScreenCombination::SCREEN_MAIN) {
307 /* second screen change to mirror or extend */
308 TLOGW(WmsLogTag::DMS, "first is already main");
309 DoFirstMainChange(firstSession, secondarySession, operateType);
310 } else if (firstCombination == ScreenCombination::SCREEN_MIRROR) {
311 /* first screen change from mirror to main */
312 TLOGW(WmsLogTag::DMS, "first screen change from mirror to main");
313 DoFirstMirrorChange(firstSession, secondarySession, operateType);
314 } else if (firstCombination == ScreenCombination::SCREEN_EXTEND) {
315 /* first screen change from extend to main */
316 TLOGW(WmsLogTag::DMS, "first screen change from extend to main");
317 DoFirstExtendChange(firstSession, secondarySession, operateType);
318 } else {
319 TLOGE(WmsLogTag::DMS, "first screen mode error");
320 }
321 }
322
DoFirstMainChangeExtend(sptr<IScreenSessionManagerClient> scbClient,sptr<ScreenSession> firstSession,sptr<ScreenSession> secondarySession)323 void MultiScreenManager::DoFirstMainChangeExtend(sptr<IScreenSessionManagerClient> scbClient,
324 sptr<ScreenSession> firstSession, sptr<ScreenSession> secondarySession)
325 {
326 TLOGW(WmsLogTag::DMS, "exec switch extend");
327 secondarySession->SetScreenCombination(ScreenCombination::SCREEN_EXTEND);
328 RSDisplayNodeConfig config = { secondarySession->screenId_, false, INVALID_NODEID};
329 secondarySession->ReuseDisplayNode(config);
330 secondarySession->SetIsExtend(true);
331 firstSession->SetIsExtend(false);
332 SessionOption secondaryOption = ScreenSessionManager::GetInstance().GetSessionOption(secondarySession);
333 scbClient->OnScreenConnectionChanged(secondaryOption, ScreenEvent::CONNECTED);
334 ScreenSessionManager::GetInstance().NotifyScreenChanged(
335 secondarySession->ConvertToScreenInfo(), ScreenChangeEvent::SCREEN_SOURCE_MODE_CHANGE);
336 TLOGW(WmsLogTag::DMS, "exec switch mirror to extend 4/6 end");
337 }
338
DoFirstMainChangeMirror(sptr<IScreenSessionManagerClient> scbClient,sptr<ScreenSession> firstSession,sptr<ScreenSession> secondarySession)339 void MultiScreenManager::DoFirstMainChangeMirror(sptr<IScreenSessionManagerClient> scbClient,
340 sptr<ScreenSession> firstSession, sptr<ScreenSession> secondarySession)
341 {
342 /* move second screen windows to first screen then set second screen to mirror */
343 /* create mirror */
344 SessionOption secondaryOption = ScreenSessionManager::GetInstance().GetSessionOption(secondarySession);
345 scbClient->OnScreenConnectionChanged(secondaryOption, ScreenEvent::DISCONNECTED);
346 /* create first screen mirror */
347 NodeId nodeId = firstSession->GetDisplayNode() == nullptr ? 0 : firstSession->GetDisplayNode()->GetId();
348 secondarySession->SetScreenCombination(ScreenCombination::SCREEN_MIRROR);
349 secondarySession->SetIsExtend(true);
350 firstSession->SetIsExtend(false);
351 RSDisplayNodeConfig config = { secondarySession->screenId_, true, nodeId };
352 secondarySession->ReuseDisplayNode(config);
353 ScreenSessionManager::GetInstance().NotifyScreenChanged(
354 secondarySession->ConvertToScreenInfo(), ScreenChangeEvent::SCREEN_SOURCE_MODE_CHANGE);
355 TLOGW(WmsLogTag::DMS, "exec switch mirror 12/14 end");
356 }
357
DoFirstMainChange(sptr<ScreenSession> firstSession,sptr<ScreenSession> secondarySession,const std::string & operateType)358 void MultiScreenManager::DoFirstMainChange(sptr<ScreenSession> firstSession, sptr<ScreenSession> secondarySession,
359 const std::string& operateType)
360 {
361 TLOGW(WmsLogTag::DMS, "enter");
362 sptr<IScreenSessionManagerClient> scbClient = ScreenSessionManager::GetInstance().GetClientProxy();
363 if (scbClient == nullptr) {
364 TLOGE(WmsLogTag::DMS, "scbClient null");
365 return;
366 }
367 firstSession->SetScreenCombination(ScreenCombination::SCREEN_MAIN);
368 ScreenCombination secondaryCombination = secondarySession->GetScreenCombination();
369 TLOGW(WmsLogTag::DMS, "current secondary screen mode:%{public}d", secondaryCombination);
370 if (operateType == SCREEN_EXTEND) {
371 TLOGW(WmsLogTag::DMS, "exec switch extend");
372 if (secondaryCombination == ScreenCombination::SCREEN_MIRROR) {
373 // mirror to extend 4,6
374 DoFirstMainChangeExtend(scbClient, firstSession, secondarySession);
375 } else {
376 TLOGW(WmsLogTag::DMS, "already extend no need to change");
377 }
378 } else if (operateType == SCREEN_MIRROR) {
379 TLOGW(WmsLogTag::DMS, "exec switch mirror");
380 if (secondaryCombination == ScreenCombination::SCREEN_EXTEND) {
381 // mirror to extend 12,14
382 DoFirstMainChangeMirror(scbClient, firstSession, secondarySession);
383 } else {
384 TLOGE(WmsLogTag::DMS, "already mirror no need to change");
385 }
386 } else {
387 TLOGE(WmsLogTag::DMS, "param error!");
388 }
389 }
390
DoFirstMirrorChangeExtend(sptr<IScreenSessionManagerClient> scbClient,sptr<ScreenSession> firstSession,sptr<ScreenSession> secondarySession)391 void MultiScreenManager::DoFirstMirrorChangeExtend(sptr<IScreenSessionManagerClient> scbClient,
392 sptr<ScreenSession> firstSession, sptr<ScreenSession> secondarySession)
393 {
394 /* change secondarySession to extend */
395 TLOGW(WmsLogTag::DMS, "exec switch extend");
396 secondarySession->SetIsExtend(true);
397 secondarySession->SetScreenCombination(ScreenCombination::SCREEN_EXTEND);
398
399 /* change firstSession from mirror to main */
400 std::shared_ptr<RSDisplayNode> displayNode = firstSession->GetDisplayNode();
401 if (displayNode != nullptr) {
402 displayNode->RemoveFromTree();
403 }
404 firstSession->SetScreenCombination(ScreenCombination::SCREEN_MAIN);
405 firstSession->ReleaseDisplayNode();
406 RSDisplayNodeConfig config = { firstSession->screenId_ };
407 firstSession->SetIsExtend(false);
408 firstSession->CreateDisplayNode(config);
409 ScreenSessionManager::GetInstance().SetDefaultScreenId(firstSession->GetScreenId());
410 SessionOption firstOption = ScreenSessionManager::GetInstance().GetSessionOption(firstSession);
411 scbClient->OnScreenConnectionChanged(firstOption, ScreenEvent::CONNECTED);
412 /* move secondarySession windows to firstSession */
413 TLOGW(WmsLogTag::DMS, "mainScreenId:%{public}" PRIu64", extendScreenId=%{public}" PRIu64,
414 firstSession->GetScreenId(), secondarySession->GetScreenId());
415 secondarySession->ScreenExtendChange(firstSession->GetScreenId(), secondarySession->GetScreenId());
416 TLOGW(WmsLogTag::DMS, "exec switch extend 1/7 end");
417 }
418
DoFirstMirrorChangeMirror(sptr<IScreenSessionManagerClient> scbClient,sptr<ScreenSession> firstSession,sptr<ScreenSession> secondarySession)419 void MultiScreenManager::DoFirstMirrorChangeMirror(sptr<IScreenSessionManagerClient> scbClient,
420 sptr<ScreenSession> firstSession, sptr<ScreenSession> secondarySession)
421 {
422 /* change firstSession from to mirror */
423 TLOGW(WmsLogTag::DMS, "exec switch mirror");
424 std::shared_ptr<RSDisplayNode> displayNode = firstSession->GetDisplayNode();
425 if (displayNode != nullptr) {
426 displayNode->RemoveFromTree();
427 }
428 firstSession->SetScreenCombination(ScreenCombination::SCREEN_MAIN);
429 firstSession->ReleaseDisplayNode();
430 RSDisplayNodeConfig config = { firstSession->screenId_ };
431 firstSession->SetIsExtend(false);
432 firstSession->CreateDisplayNode(config);
433 ScreenSessionManager::GetInstance().SetDefaultScreenId(firstSession->GetScreenId());
434 SessionOption firstOption = ScreenSessionManager::GetInstance().GetSessionOption(firstSession);
435 scbClient->OnScreenConnectionChanged(firstOption, ScreenEvent::CONNECTED);
436 /* move secondarySession windows to firstSession */
437 /* change secondarySession to mirror */
438 /* create mirror */
439 SessionOption secondaryOption = ScreenSessionManager::GetInstance().GetSessionOption(secondarySession);
440 scbClient->OnScreenConnectionChanged(secondaryOption, ScreenEvent::DISCONNECTED);
441 /* create inner screen's mirror */
442 NodeId nodeId = firstSession->GetDisplayNode() == nullptr ? 0 : firstSession->GetDisplayNode()->GetId();
443 secondarySession->SetScreenCombination(ScreenCombination::SCREEN_MIRROR);
444 secondarySession->SetIsExtend(true);
445 config = {secondarySession->screenId_, true, nodeId };
446 secondarySession->ReuseDisplayNode(config);
447 TLOGW(WmsLogTag::DMS, "exec switch mirror 2/3/5/8 end");
448 }
449
DoFirstMirrorChange(sptr<ScreenSession> firstSession,sptr<ScreenSession> secondarySession,const std::string & operateType)450 void MultiScreenManager::DoFirstMirrorChange(sptr<ScreenSession> firstSession, sptr<ScreenSession> secondarySession,
451 const std::string& operateType)
452 {
453 TLOGW(WmsLogTag::DMS, "enter");
454 sptr<IScreenSessionManagerClient> scbClient = ScreenSessionManager::GetInstance().GetClientProxy();
455 if (scbClient == nullptr) {
456 TLOGE(WmsLogTag::DMS, "scbClient null");
457 return;
458 }
459 if (operateType == SCREEN_EXTEND) {
460 // 1, 7
461 DoFirstMirrorChangeExtend(scbClient, firstSession, secondarySession);
462 } else if (operateType == SCREEN_MIRROR) {
463 // 2 3 5 8
464 DoFirstMirrorChangeMirror(scbClient, firstSession, secondarySession);
465 } else {
466 TLOGE(WmsLogTag::DMS, "param error!");
467 }
468 }
469
DoFirstExtendChangeExtend(sptr<ScreenSession> firstSession,sptr<ScreenSession> secondarySession)470 void MultiScreenManager::DoFirstExtendChangeExtend(sptr<ScreenSession> firstSession,
471 sptr<ScreenSession> secondarySession)
472 {
473 /* set firstSession main */
474 TLOGW(WmsLogTag::DMS, "exec switch extend");
475 firstSession->SetIsExtend(false);
476 firstSession->SetScreenCombination(ScreenCombination::SCREEN_MAIN);
477 ScreenSessionManager::GetInstance().SetDefaultScreenId(firstSession->GetScreenId());
478 /* set secondarySession extend */
479 secondarySession->SetIsExtend(true);
480 secondarySession->SetScreenCombination(ScreenCombination::SCREEN_EXTEND);
481 TLOGW(WmsLogTag::DMS, "mainScreenId:%{public}" PRIu64", extendScreenId=%{public}" PRIu64,
482 firstSession->GetScreenId(), secondarySession->GetScreenId());
483 firstSession->ScreenExtendChange(firstSession->GetScreenId(), secondarySession->GetScreenId());
484 TLOGW(WmsLogTag::DMS, "exec switch extend 9/11/13/15 end");
485 /* change main and extend screens's windows */
486 }
487
DoFirstExtendChangeMirror(sptr<ScreenSession> firstSession,sptr<ScreenSession> secondarySession)488 void MultiScreenManager::DoFirstExtendChangeMirror(sptr<ScreenSession> firstSession,
489 sptr<ScreenSession> secondarySession)
490 {
491 sptr<IScreenSessionManagerClient> scbClient = ScreenSessionManager::GetInstance().GetClientProxy();
492 if (scbClient == nullptr) {
493 TLOGE(WmsLogTag::DMS, "scbClient null");
494 return;
495 }
496 /* set firstSession main screen */
497 TLOGW(WmsLogTag::DMS, "exec switch mirror");
498 firstSession->SetIsExtend(false);
499 firstSession->SetScreenCombination(ScreenCombination::SCREEN_MAIN);
500 ScreenSessionManager::GetInstance().SetDefaultScreenId(firstSession->GetScreenId());
501 TLOGW(WmsLogTag::DMS, "mainScreenId:%{public}" PRIu64", extendScreenId=%{public}" PRIu64,
502 firstSession->GetScreenId(), secondarySession->GetScreenId());
503 firstSession->ScreenExtendChange(firstSession->GetScreenId(), secondarySession->GetScreenId());
504 /* move secondarySession windows to firstSession => join two screens window to firstSession */
505 /* create mirror */
506 SessionOption secondaryOption = ScreenSessionManager::GetInstance().GetSessionOption(secondarySession);
507 scbClient->OnScreenConnectionChanged(secondaryOption, ScreenEvent::DISCONNECTED);
508 /* create inner screen's mirror node */
509 NodeId nodeId = firstSession->GetDisplayNode() == nullptr ? 0 : firstSession->GetDisplayNode()->GetId();
510 secondarySession->SetScreenCombination(ScreenCombination::SCREEN_MIRROR);
511 secondarySession->SetIsExtend(true);
512 RSDisplayNodeConfig config = { secondarySession->screenId_, true, nodeId };
513 secondarySession->ReuseDisplayNode(config);
514 TLOGW(WmsLogTag::DMS, "exec switch mirror 10/16 end");
515 }
516
DoFirstExtendChange(sptr<ScreenSession> firstSession,sptr<ScreenSession> secondarySession,const std::string & operateType)517 void MultiScreenManager::DoFirstExtendChange(sptr<ScreenSession> firstSession, sptr<ScreenSession> secondarySession,
518 const std::string& operateType)
519 {
520 TLOGW(WmsLogTag::DMS, "enter");
521 if (operateType == SCREEN_EXTEND) {
522 // 9 11 13 15
523 DoFirstExtendChangeExtend(firstSession, secondarySession);
524 } else if (operateType == SCREEN_MIRROR) {
525 // 10 16
526 DoFirstExtendChangeMirror(firstSession, secondarySession);
527 } else {
528 TLOGE(WmsLogTag::DMS, "param error!");
529 }
530 }
531
SetLastScreenMode(ScreenId mainScreenId,MultiScreenMode secondaryScreenMode)532 void MultiScreenManager::SetLastScreenMode(ScreenId mainScreenId, MultiScreenMode secondaryScreenMode)
533 {
534 lastScreenMode_.first = mainScreenId;
535 lastScreenMode_.second = secondaryScreenMode;
536 TLOGW(WmsLogTag::DMS, "success, mainScreenId = %{public}" PRIu64
537 ", secondaryScreenMode = %{public}d", lastScreenMode_.first, lastScreenMode_.second);
538 }
539
InternalScreenOnChange(sptr<ScreenSession> internalSession,sptr<ScreenSession> externalSession)540 void MultiScreenManager::InternalScreenOnChange(sptr<ScreenSession> internalSession,
541 sptr<ScreenSession> externalSession)
542 {
543 if (internalSession == nullptr || externalSession == nullptr) {
544 TLOGE(WmsLogTag::DMS, "internal or external screen is null!");
545 return;
546 }
547 ScreenId mainScreenId = lastScreenMode_.first;
548 MultiScreenMode secondaryScreenMode = lastScreenMode_.second;
549 if (mainScreenId == SCREEN_ID_INVALID) {
550 TLOGW(WmsLogTag::DMS, "mode not restored, reset last screen mode");
551 ScreenSessionManager::GetInstance().SetLastScreenMode(internalSession, externalSession);
552 return;
553 }
554 ScreenId internalScreenId = ScreenSessionManager::GetInstance().GetInternalScreenId();
555 if (mainScreenId == internalScreenId && secondaryScreenMode == MultiScreenMode::SCREEN_MIRROR) {
556 DoFirstMirrorChange(internalSession, externalSession, SCREEN_MIRROR);
557 TLOGW(WmsLogTag::DMS, "5: external mirror to internal mirror");
558 } else if (mainScreenId == internalScreenId && secondaryScreenMode == MultiScreenMode::SCREEN_EXTEND) {
559 DoFirstMirrorChange(internalSession, externalSession, SCREEN_EXTEND);
560 TLOGW(WmsLogTag::DMS, "7: external mirror to internal extend");
561 } else if (mainScreenId != internalScreenId && secondaryScreenMode == MultiScreenMode::SCREEN_EXTEND) {
562 DoFirstMainChange(externalSession, internalSession, SCREEN_EXTEND);
563 TLOGW(WmsLogTag::DMS, "6: external mirror to external extend");
564 } else {
565 TLOGE(WmsLogTag::DMS, "no need to change or paramater error!");
566 }
567 if (secondaryScreenMode == MultiScreenMode::SCREEN_MIRROR) {
568 MultiScreenReportDataToRss(SCREEN_MIRROR, MULTI_SCREEN_ENTER_STR);
569 } else if (secondaryScreenMode == MultiScreenMode::SCREEN_EXTEND) {
570 MultiScreenReportDataToRss(SCREEN_EXTEND, MULTI_SCREEN_ENTER_STR);
571 }
572 }
573
InternalScreenOffChange(sptr<ScreenSession> internalSession,sptr<ScreenSession> externalSession)574 void MultiScreenManager::InternalScreenOffChange(sptr<ScreenSession> internalSession,
575 sptr<ScreenSession> externalSession)
576 {
577 if (internalSession == nullptr || externalSession == nullptr) {
578 TLOGE(WmsLogTag::DMS, "internal or external screen is null!");
579 return;
580 }
581 ScreenSessionManager::GetInstance().SetLastScreenMode(internalSession, externalSession);
582 ScreenId mainScreenId = lastScreenMode_.first;
583 MultiScreenMode secondaryScreenMode = lastScreenMode_.second;
584 ScreenId internalScreenId = ScreenSessionManager::GetInstance().GetInternalScreenId();
585 if (mainScreenId == internalScreenId && secondaryScreenMode == MultiScreenMode::SCREEN_MIRROR) {
586 DoFirstMirrorChange(externalSession, internalSession, SCREEN_MIRROR);
587 MultiScreenReportDataToRss(SCREEN_MIRROR, MULTI_SCREEN_EXIT_STR);
588 TLOGW(WmsLogTag::DMS, "3: internal mirror to external mirror");
589 } else if (mainScreenId == internalScreenId && secondaryScreenMode == MultiScreenMode::SCREEN_EXTEND) {
590 DoFirstExtendChange(externalSession, internalSession, SCREEN_MIRROR);
591 MultiScreenReportDataToRss(SCREEN_EXTEND, MULTI_SCREEN_EXIT_STR);
592 TLOGW(WmsLogTag::DMS, "10: internal extend to external mirror");
593 } else if (mainScreenId != internalScreenId && secondaryScreenMode == MultiScreenMode::SCREEN_EXTEND) {
594 DoFirstMainChange(externalSession, internalSession, SCREEN_MIRROR);
595 MultiScreenReportDataToRss(SCREEN_EXTEND, MULTI_SCREEN_EXIT_STR);
596 TLOGW(WmsLogTag::DMS, "14: external extend to external mirror");
597 } else {
598 MultiScreenReportDataToRss(SCREEN_MIRROR, MULTI_SCREEN_EXIT_STR);
599 TLOGE(WmsLogTag::DMS, "no need to change or paramater error!");
600 }
601 }
602
ExternalScreenDisconnectChange(sptr<ScreenSession> internalSession,sptr<ScreenSession> externalSession)603 void MultiScreenManager::ExternalScreenDisconnectChange(sptr<ScreenSession> internalSession,
604 sptr<ScreenSession> externalSession)
605 {
606 if (internalSession == nullptr || externalSession == nullptr) {
607 TLOGE(WmsLogTag::DMS, "internal or external screen is null!");
608 return;
609 }
610 ScreenCombination internalCombination = internalSession->GetScreenCombination();
611 ScreenCombination externalCombination = externalSession->GetScreenCombination();
612 if (externalCombination != ScreenCombination::SCREEN_MAIN) {
613 DoFirstMainChange(internalSession, externalSession, SCREEN_MIRROR);
614 TLOGW(WmsLogTag::DMS, "12: internal extend to internal mirror");
615 return;
616 }
617 if (internalCombination == ScreenCombination::SCREEN_MIRROR) {
618 DoFirstMirrorChange(internalSession, externalSession, SCREEN_MIRROR);
619 TLOGW(WmsLogTag::DMS, "8: external mirror to internal mirror");
620 } else if (internalCombination == ScreenCombination::SCREEN_EXTEND) {
621 DoFirstExtendChange(internalSession, externalSession, SCREEN_MIRROR);
622 TLOGW(WmsLogTag::DMS, "16: external extend to internal mirror");
623 } else {
624 TLOGE(WmsLogTag::DMS, "paramater error!");
625 return;
626 }
627 }
628
AreScreensTouching(sptr<ScreenSession> mainScreenSession,sptr<ScreenSession> secondScreenSession,MultiScreenPositionOptions mainScreenOptions,MultiScreenPositionOptions secondScreenOption)629 bool MultiScreenManager::AreScreensTouching(sptr<ScreenSession> mainScreenSession,
630 sptr<ScreenSession> secondScreenSession, MultiScreenPositionOptions mainScreenOptions,
631 MultiScreenPositionOptions secondScreenOption)
632 {
633 ScreenProperty mainProperty = mainScreenSession->GetScreenProperty();
634 uint32_t mainScreenWidth = static_cast<uint32_t>(mainProperty.GetBounds().rect_.GetWidth());
635 uint32_t mainScreenHeight = static_cast<uint32_t>(mainProperty.GetBounds().rect_.GetHeight());
636
637 ScreenProperty secondProperty = secondScreenSession->GetScreenProperty();
638 uint32_t secondScreenWidth = static_cast<uint32_t>(secondProperty.GetBounds().rect_.GetWidth());
639 uint32_t secondScreenHeight = static_cast<uint32_t>(secondProperty.GetBounds().rect_.GetHeight());
640
641 bool horizontalTouchingAB = (mainScreenOptions.startX_ + mainScreenWidth == secondScreenOption.startX_);
642 bool horizontalTouchingBA = (secondScreenOption.startX_ + secondScreenWidth == mainScreenOptions.startX_);
643 bool horizontalTouching = (horizontalTouchingAB || horizontalTouchingBA);
644
645 bool verticalTouchingAB = (mainScreenOptions.startY_ + mainScreenHeight == secondScreenOption.startY_);
646 bool verticalTouchingBA = (secondScreenOption.startY_ + secondScreenHeight == mainScreenOptions.startY_);
647 bool verticalTouching = (verticalTouchingAB || verticalTouchingBA);
648
649 if ((horizontalTouchingAB && verticalTouchingAB) || (horizontalTouchingBA && verticalTouchingBA)) {
650 return false;
651 }
652 return horizontalTouching || verticalTouching;
653 }
654
MultiScreenReportDataToRss(std::string multiScreenType,std::string status)655 void MultiScreenManager::MultiScreenReportDataToRss(std::string multiScreenType, std::string status)
656 {
657 #ifdef RES_SCHED_ENABLE
658 TLOGI(WmsLogTag::DMS, "type:%{public}s, status:%{public}s", multiScreenType.c_str(), status.c_str());
659 uint32_t type = OHOS::ResourceSchedule::ResType::RES_TYPE_DISPLAY_MULTI_SCREEN;
660 std::unordered_map<std::string, std::string> payload = {
661 { "type", multiScreenType },
662 { "status", status },
663 };
664 int32_t value = status == MULTI_SCREEN_ENTER_STR ? MULTI_SCREEN_ENTER : MULTI_SCREEN_EXIT;
665 OHOS::ResourceSchedule::ResSchedClient::GetInstance().ReportData(type, value, payload);
666 #endif
667 }
668 } // namespace OHOS::Rosen
669