• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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