• 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 #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