1 /*
2 * Copyright (c) 2025 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_change_utils.h"
17
18 #include <transaction/rs_transaction.h>
19
20 #include "fold_screen_state_internel.h"
21 #include "fold_screen_controller/super_fold_state_manager.h"
22 #include "rs_adapter.h"
23 #include "screen_session_manager.h"
24 #include "window_manager_hilog.h"
25
26 namespace OHOS {
27 namespace Rosen {
28
ScreenPropertyChangeNotify(sptr<ScreenSession> & innerScreen,sptr<ScreenSession> & externalScreen)29 void MultiScreenChangeUtils::ScreenPropertyChangeNotify(sptr<ScreenSession>& innerScreen,
30 sptr<ScreenSession>& externalScreen)
31 {
32 if (innerScreen != nullptr) {
33 ScreenProperty property = innerScreen->GetScreenProperty();
34 property.SetPropertyChangeReason("screen mode change");
35 TLOGW(WmsLogTag::DMS, "property change screenId=%{public}" PRIu64, innerScreen->GetScreenId());
36 innerScreen->PropertyChange(property, ScreenPropertyChangeReason::CHANGE_MODE);
37 ScreenSessionManager::GetInstance().NotifyScreenChanged(innerScreen->ConvertToScreenInfo(),
38 ScreenChangeEvent::CHANGE_MODE);
39 ScreenSessionManager::GetInstance().NotifyDisplayChanged(innerScreen->ConvertToDisplayInfo(),
40 DisplayChangeEvent::DISPLAY_SIZE_CHANGED);
41 }
42 if (externalScreen != nullptr) {
43 ScreenProperty property = externalScreen->GetScreenProperty();
44 property.SetPropertyChangeReason("screen mode change");
45 TLOGW(WmsLogTag::DMS, "property change screenId=%{public}" PRIu64, externalScreen->GetScreenId());
46 externalScreen->PropertyChange(property, ScreenPropertyChangeReason::CHANGE_MODE);
47 ScreenSessionManager::GetInstance().NotifyScreenChanged(externalScreen->ConvertToScreenInfo(),
48 ScreenChangeEvent::CHANGE_MODE);
49 ScreenSessionManager::GetInstance().NotifyDisplayChanged(externalScreen->ConvertToDisplayInfo(),
50 DisplayChangeEvent::DISPLAY_SIZE_CHANGED);
51 }
52 }
53
ScreenDensityChangeNotify(sptr<ScreenSession> innerScreen,sptr<ScreenSession> externalScreen)54 void MultiScreenChangeUtils::ScreenDensityChangeNotify(sptr<ScreenSession> innerScreen,
55 sptr<ScreenSession> externalScreen)
56 {
57 if (innerScreen != nullptr) {
58 ScreenSessionManager::GetInstance().SetVirtualPixelRatio(innerScreen->GetScreenId(),
59 innerScreen->GetScreenProperty().GetVirtualPixelRatio());
60 }
61 if (externalScreen != nullptr) {
62 ScreenSessionManager::GetInstance().SetVirtualPixelRatio(externalScreen->GetScreenId(),
63 externalScreen->GetScreenProperty().GetVirtualPixelRatio());
64 }
65 }
66
ScreenExtendPositionChange(sptr<ScreenSession> & innerScreen,sptr<ScreenSession> & externalScreen)67 void MultiScreenChangeUtils::ScreenExtendPositionChange(sptr<ScreenSession>& innerScreen,
68 sptr<ScreenSession>& externalScreen)
69 {
70 if (innerScreen == nullptr || externalScreen == nullptr) {
71 TLOGE(WmsLogTag::DMS, "screenSession null.");
72 return;
73 }
74 innerScreen->PropertyChange(innerScreen->GetScreenProperty(),
75 ScreenPropertyChangeReason::RELATIVE_POSITION_CHANGE);
76 externalScreen->PropertyChange(externalScreen->GetScreenProperty(),
77 ScreenPropertyChangeReason::RELATIVE_POSITION_CHANGE);
78 {
79 std::shared_ptr<RSDisplayNode> innerNode = innerScreen->GetDisplayNode();
80 std::shared_ptr<RSDisplayNode> externalNode = externalScreen->GetDisplayNode();
81 if (innerNode && externalNode) {
82 ScreenSessionManager::GetInstance().SetScreenOffset(innerScreen->GetScreenId(),
83 innerScreen->GetScreenProperty().GetStartX(),
84 innerScreen->GetScreenProperty().GetStartY());
85 ScreenSessionManager::GetInstance().SetScreenOffset(externalScreen->GetScreenId(),
86 externalScreen->GetScreenProperty().GetStartX(),
87 externalScreen->GetScreenProperty().GetStartY());
88 } else {
89 TLOGW(WmsLogTag::DMS, "DisplayNode is null");
90 }
91 }
92 RSTransactionAdapter::FlushImplicitTransaction(
93 {innerScreen->GetRSUIContext(), externalScreen->GetRSUIContext()});
94 }
95
SetScreenAvailableStatus(sptr<ScreenSession> & screenSession,bool isScreenAvailable)96 void MultiScreenChangeUtils::SetScreenAvailableStatus(sptr<ScreenSession>& screenSession,
97 bool isScreenAvailable)
98 {
99 if (!screenSession) {
100 TLOGE(WmsLogTag::DMS, "screenSession is null");
101 return;
102 }
103 ScreenId screenId = screenSession->GetScreenId();
104 TLOGW(WmsLogTag::DMS, "screenId=%{public}" PRIu64, screenId);
105 screenSession->SetScreenAvailableStatus(isScreenAvailable);
106 if (isScreenAvailable) {
107 ScreenSessionManager::GetInstance().NotifyDisplayCreate(
108 screenSession->ConvertToDisplayInfo());
109 } else {
110 ScreenSessionManager::GetInstance().NotifyDisplayDestroy(screenId);
111 }
112 }
113
ScreenMainPositionChange(sptr<ScreenSession> & innerScreen,sptr<ScreenSession> & externalScreen)114 void MultiScreenChangeUtils::ScreenMainPositionChange(sptr<ScreenSession>& innerScreen,
115 sptr<ScreenSession>& externalScreen)
116 {
117 if (innerScreen == nullptr || externalScreen == nullptr) {
118 TLOGE(WmsLogTag::DMS, "screenSession is null");
119 return;
120 }
121 innerScreen->SetStartPosition(0, 0);
122 innerScreen->SetXYPosition(0, 0);
123 innerScreen->PropertyChange(innerScreen->GetScreenProperty(),
124 ScreenPropertyChangeReason::RELATIVE_POSITION_CHANGE);
125 externalScreen->SetStartPosition(0, 0);
126 externalScreen->SetXYPosition(0, 0);
127 externalScreen->PropertyChange(externalScreen->GetScreenProperty(),
128 ScreenPropertyChangeReason::RELATIVE_POSITION_CHANGE);
129 {
130 std::shared_ptr<RSDisplayNode> innerNode = innerScreen->GetDisplayNode();
131 std::shared_ptr<RSDisplayNode> externalNode = externalScreen->GetDisplayNode();
132 if (innerNode && externalNode) {
133 ScreenSessionManager::GetInstance().SetScreenOffset(innerScreen->GetScreenId(), 0, 0);
134 ScreenSessionManager::GetInstance().SetScreenOffset(externalScreen->GetScreenId(), 0, 0);
135 } else {
136 TLOGW(WmsLogTag::DMS, "DisplayNode is null");
137 }
138 }
139 RSTransactionAdapter::FlushImplicitTransaction(
140 {innerScreen->GetRSUIContext(), externalScreen->GetRSUIContext()});
141 ScreenSessionManager::GetInstance().NotifyDisplayChanged(innerScreen->ConvertToDisplayInfo(),
142 DisplayChangeEvent::DISPLAY_SIZE_CHANGED);
143 ScreenSessionManager::GetInstance().NotifyDisplayChanged(externalScreen->ConvertToDisplayInfo(),
144 DisplayChangeEvent::DISPLAY_SIZE_CHANGED);
145 }
146
SetExternalScreenOffScreenRendering(sptr<ScreenSession> & innerScreen,sptr<ScreenSession> & externalScreen)147 void MultiScreenChangeUtils::SetExternalScreenOffScreenRendering(sptr<ScreenSession>& innerScreen,
148 sptr<ScreenSession>& externalScreen)
149 {
150 if (innerScreen != nullptr) {
151 TLOGW(WmsLogTag::DMS, "inner screen offScreen rendering.");
152 innerScreen->SetScreenOffScreenRendering();
153 }
154 if (externalScreen != nullptr) {
155 TLOGW(WmsLogTag::DMS, "external screen offScreen rendering.");
156 externalScreen->SetScreenOffScreenRendering();
157 }
158 }
159
ScreenCombinationChange(sptr<ScreenSession> & innerScreen,sptr<ScreenSession> & externalScreen,ScreenCombination externalCombination)160 void MultiScreenChangeUtils::ScreenCombinationChange(sptr<ScreenSession>& innerScreen,
161 sptr<ScreenSession>& externalScreen, ScreenCombination externalCombination)
162 {
163 if (innerScreen == nullptr || externalScreen == nullptr) {
164 TLOGE(WmsLogTag::DMS, "screenSession null.");
165 return;
166 }
167 /* set inner screen local info */
168 innerScreen->SetScreenCombination(ScreenCombination::SCREEN_MAIN);
169 innerScreen->SetIsExtend(false);
170
171 /* set external screen local info */
172 externalScreen->SetScreenCombination(externalCombination);
173 externalScreen->SetIsExtend(true);
174
175 sptr<IScreenSessionManagerClient> ssmClient = ScreenSessionManager::GetInstance().GetClientProxy();
176 if (ssmClient == nullptr) {
177 TLOGE(WmsLogTag::DMS, "ssmClient null");
178 return;
179 }
180 ssmClient->SetScreenCombination(innerScreen->GetScreenId(), externalScreen->GetScreenId(), externalCombination);
181 }
182
ScreenSerialNumberChange(sptr<ScreenSession> & innerScreen,sptr<ScreenSession> & externalScreen)183 void MultiScreenChangeUtils::ScreenSerialNumberChange(sptr<ScreenSession>& innerScreen,
184 sptr<ScreenSession>& externalScreen)
185 {
186 if (innerScreen == nullptr || externalScreen == nullptr) {
187 TLOGE(WmsLogTag::DMS, "screen sessions null.");
188 return;
189 }
190 std::string innerScreenSN = innerScreen->GetSerialNumber();
191 std::string externalScreenSN = externalScreen->GetSerialNumber();
192 innerScreen->SetSerialNumber(externalScreenSN);
193 externalScreen->SetSerialNumber(innerScreenSN);
194 }
195
ScreenActiveModesChange(sptr<ScreenSession> & innerScreen,sptr<ScreenSession> & externalScreen)196 void MultiScreenChangeUtils::ScreenActiveModesChange(sptr<ScreenSession>& innerScreen,
197 sptr<ScreenSession>& externalScreen)
198 {
199 if (innerScreen == nullptr || externalScreen == nullptr) {
200 TLOGE(WmsLogTag::DMS, "screen sessions null.");
201 return;
202 }
203 std::vector<sptr<SupportedScreenModes>> innerScreenModes = innerScreen->GetScreenModes();
204 std::vector<sptr<SupportedScreenModes>> externalScreenModes = externalScreen->GetScreenModes();
205 innerScreen->SetScreenModes(externalScreenModes);
206 externalScreen->SetScreenModes(innerScreenModes);
207
208 int32_t innerActiveId = innerScreen->GetActiveId();
209 int32_t externalActiveId = externalScreen->GetActiveId();
210 innerScreen->SetActiveId(externalActiveId);
211 externalScreen->SetActiveId(innerActiveId);
212 }
213
ScreenRSIdChange(sptr<ScreenSession> & innerScreen,sptr<ScreenSession> & externalScreen)214 void MultiScreenChangeUtils::ScreenRSIdChange(sptr<ScreenSession>& innerScreen,
215 sptr<ScreenSession>& externalScreen)
216 {
217 if (innerScreen == nullptr || externalScreen == nullptr) {
218 TLOGE(WmsLogTag::DMS, "screen sessions null.");
219 return;
220 }
221
222 ScreenSessionManager::GetInstance().UpdateScreenIdManager(innerScreen, externalScreen);
223
224 ScreenId innerScreenId = innerScreen->GetRSScreenId();
225 ScreenId externalScreenId = externalScreen->GetRSScreenId();
226 innerScreen->SetRSScreenId(externalScreenId);
227 externalScreen->SetRSScreenId(innerScreenId);
228
229 bool isInnerScreenInternal = innerScreen->GetIsInternal();
230 bool isexternalScreenInternal = externalScreen->GetIsInternal();
231 innerScreen->SetIsInternal(isexternalScreenInternal);
232 externalScreen->SetIsInternal(isInnerScreenInternal);
233 }
234
ScreenNameChange(sptr<ScreenSession> & innerScreen,sptr<ScreenSession> & externalScreen)235 void MultiScreenChangeUtils::ScreenNameChange(sptr<ScreenSession>& innerScreen,
236 sptr<ScreenSession>& externalScreen)
237 {
238 if (innerScreen == nullptr || externalScreen == nullptr) {
239 TLOGE(WmsLogTag::DMS, "screen sessions null.");
240 return;
241 }
242 std::string innerScreenName = innerScreen->GetName();
243 std::string externalScreenName = externalScreen->GetName();
244 innerScreen->SetName(externalScreenName);
245 externalScreen->SetName(innerScreenName);
246 }
247
ScreenPropertyChange(sptr<ScreenSession> & innerScreen,sptr<ScreenSession> & externalScreen)248 void MultiScreenChangeUtils::ScreenPropertyChange(sptr<ScreenSession>& innerScreen,
249 sptr<ScreenSession>& externalScreen)
250 {
251 if (innerScreen == nullptr || externalScreen == nullptr) {
252 TLOGE(WmsLogTag::DMS, "screen sessions null.");
253 return;
254 }
255 /* change property from physical session */
256 sptr<ScreenSession> innerPhyScreen =
257 ScreenSessionManager::GetInstance().GetPhysicalScreenSession(innerScreen->GetRSScreenId());
258 sptr<ScreenSession> externalPhyScreen =
259 ScreenSessionManager::GetInstance().GetPhysicalScreenSession(externalScreen->GetRSScreenId());
260
261 if (innerPhyScreen == nullptr || externalPhyScreen == nullptr) {
262 TLOGE(WmsLogTag::DMS, "physicalScreen is null!");
263 return;
264 }
265 std::ostringstream oss;
266 oss << "innerPhyScreen screenId:" << innerPhyScreen->GetScreenId()
267 << ", rsId:" << innerPhyScreen->GetRSScreenId()
268 << ", externalPhyScreen screenId:" << externalPhyScreen->GetRSScreenId()
269 << ", rsId:" << externalPhyScreen->GetRSScreenId();
270 oss << std::endl;
271 TLOGW(WmsLogTag::DMS, "%{public}s", oss.str().c_str());
272
273 ScreenProperty innerPhyProperty = innerPhyScreen->GetScreenProperty();
274 ScreenProperty externalPhyProperty = externalPhyScreen->GetScreenProperty();
275 innerScreen->SetScreenProperty(externalPhyProperty);
276 externalScreen->SetScreenProperty(innerPhyProperty);
277 }
278
ExchangeScreenSupportedRefreshRate(sptr<ScreenSession> & innerScreen,sptr<ScreenSession> & externalScreen)279 void MultiScreenChangeUtils::ExchangeScreenSupportedRefreshRate(sptr<ScreenSession>& innerScreen,
280 sptr<ScreenSession>& externalScreen)
281 {
282 if (innerScreen == nullptr || externalScreen == nullptr) {
283 TLOGE(WmsLogTag::DMS, "screen sessions null.");
284 return;
285 }
286 /* change screen supported refresh rate from physical session */
287 sptr<ScreenSession> innerPhyScreen =
288 ScreenSessionManager::GetInstance().GetPhysicalScreenSession(innerScreen->GetRSScreenId());
289 sptr<ScreenSession> externalPhyScreen =
290 ScreenSessionManager::GetInstance().GetPhysicalScreenSession(externalScreen->GetRSScreenId());
291
292 if (innerPhyScreen == nullptr || externalPhyScreen == nullptr) {
293 TLOGE(WmsLogTag::DMS, "physicalScreen is null!");
294 return;
295 }
296
297 std::vector<uint32_t> innerSupportedRefreshRate = innerPhyScreen->GetSupportedRefreshRate();
298 std::vector<uint32_t> externalSupportedRefreshRate = externalPhyScreen->GetSupportedRefreshRate();
299 innerScreen->SetSupportedRefreshRate(std::move(externalSupportedRefreshRate));
300 externalScreen->SetSupportedRefreshRate(std::move(innerSupportedRefreshRate));
301 }
302
SetScreenNotifyFlag(sptr<ScreenSession> & innerScreen,sptr<ScreenSession> & externalScreen)303 void MultiScreenChangeUtils::SetScreenNotifyFlag(sptr<ScreenSession>& innerScreen,
304 sptr<ScreenSession>& externalScreen)
305 {
306 if (innerScreen == nullptr || externalScreen == nullptr) {
307 TLOGE(WmsLogTag::DMS, "screen sessions null.");
308 return;
309 }
310 innerScreen->SetIsAvailableAreaNeedNotify(true);
311 externalScreen->SetIsAvailableAreaNeedNotify(true);
312 }
313
ScreenPhysicalInfoChange(sptr<ScreenSession> & innerScreen,sptr<ScreenSession> & externalScreen)314 void MultiScreenChangeUtils::ScreenPhysicalInfoChange(sptr<ScreenSession>& innerScreen,
315 sptr<ScreenSession>& externalScreen)
316 {
317 if (innerScreen == nullptr || externalScreen == nullptr) {
318 TLOGE(WmsLogTag::DMS, "screen sessions null.");
319 return;
320 }
321 std::ostringstream oss;
322 oss << "before innerScreen screenId: " << innerScreen->GetScreenId()
323 << ", rsId: " << innerScreen->GetRSScreenId()
324 << ", name: " << innerScreen->GetName()
325 << ", externalScreen screenId: " << externalScreen->GetScreenId()
326 << ", rsId: " << externalScreen->GetRSScreenId()
327 << ", name: " << externalScreen->GetName();
328 oss << std::endl;
329 TLOGW(WmsLogTag::DMS, "%{public}s", oss.str().c_str());
330
331 /* change screen property */
332 ScreenPropertyChange(innerScreen, externalScreen);
333
334 /* change screen supported refresh rate */
335 ExchangeScreenSupportedRefreshRate(innerScreen, externalScreen);
336
337 /* change screen rsId */
338 ScreenRSIdChange(innerScreen, externalScreen);
339
340 /* change screen name */
341 ScreenNameChange(innerScreen, externalScreen);
342
343 /* change serial number */
344 ScreenSerialNumberChange(innerScreen, externalScreen);
345
346 /* change active mode */
347 ScreenActiveModesChange(innerScreen, externalScreen);
348
349 /* set notify flag */
350 SetScreenNotifyFlag(innerScreen, externalScreen);
351 oss.str("");
352 oss << "after innerScreen screenId: " << innerScreen->GetScreenId()
353 << ", rsId: " << innerScreen->GetRSScreenId()
354 << ", name: " << innerScreen->GetName()
355 << ", externalScreen screenId: " << externalScreen->GetScreenId()
356 << ", rsId: " << externalScreen->GetRSScreenId()
357 << ", name: " << externalScreen->GetName();
358 oss << std::endl;
359 TLOGW(WmsLogTag::DMS, "%{public}s", oss.str().c_str());
360 }
361
CreateMirrorSession(sptr<ScreenSession> & mainSession,sptr<ScreenSession> & screenSession)362 void MultiScreenChangeUtils::CreateMirrorSession(sptr<ScreenSession>& mainSession,
363 sptr<ScreenSession>& screenSession)
364 {
365 if (mainSession == nullptr || screenSession == nullptr) {
366 TLOGE(WmsLogTag::DMS, "screenSession is null.");
367 return;
368 }
369 std::shared_ptr<RSDisplayNode> displayNode = mainSession->GetDisplayNode();
370 if (displayNode == nullptr) {
371 TLOGE(WmsLogTag::DMS, "displayNode is null.");
372 return;
373 }
374 screenSession->SetScreenCombination(ScreenCombination::SCREEN_MIRROR);
375 screenSession->SetIsExtend(true);
376 #ifdef FOLD_ABILITY_ENABLE
377 if (FoldScreenStateInternel::IsSuperFoldDisplayDevice()) {
378 SuperFoldStateManager::GetInstance().RefreshExternalRegion();
379 } else {
380 #endif
381 RSDisplayNodeConfig config = { screenSession->rsId_, true, displayNode->GetId() };
382 screenSession->ReuseDisplayNode(config);
383 #ifdef FOLD_ABILITY_ENABLE
384 }
385 #endif
386 }
387
ScreenConnectionChange(sptr<IScreenSessionManagerClient> ssmClient,sptr<ScreenSession> & screenSession,ScreenEvent screenEvent)388 void MultiScreenChangeUtils::ScreenConnectionChange(sptr<IScreenSessionManagerClient> ssmClient,
389 sptr<ScreenSession>& screenSession, ScreenEvent screenEvent)
390 {
391 if (ssmClient == nullptr || screenSession == nullptr) {
392 TLOGE(WmsLogTag::DMS, "ssmClient or screenSession is null.");
393 return;
394 }
395 SessionOption option = {
396 .rsId_ = screenSession->GetRSScreenId(),
397 .name_ = screenSession->GetName(),
398 .isExtend_ = screenSession->GetIsExtend(),
399 .innerName_ = screenSession->GetInnerName(),
400 .screenId_ = screenSession->GetScreenId(),
401 };
402 ssmClient->OnScreenConnectionChanged(option, screenEvent);
403 }
404
CreateExtendSession(sptr<ScreenSession> & screenSession)405 void MultiScreenChangeUtils::CreateExtendSession(sptr<ScreenSession>& screenSession)
406 {
407 if (screenSession == nullptr) {
408 TLOGE(WmsLogTag::DMS, "screenSession is null.");
409 return;
410 }
411 screenSession->SetIsExtend(true);
412 screenSession->SetScreenCombination(ScreenCombination::SCREEN_EXTEND);
413 RSDisplayNodeConfig config = { screenSession->rsId_, false, INVALID_NODEID };
414 screenSession->ReuseDisplayNode(config);
415 }
416
SetMultiScreenModeChangeTracker(std::string changeProc)417 void MultiScreenChangeUtils::SetMultiScreenModeChangeTracker(std::string changeProc)
418 {
419 ScreenSessionManager::GetInstance().SetMultiScreenModeChangeTracker(changeProc);
420 }
421 } // Rosen
422 } // OHOS