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