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