• 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_power_change_manager.h"
17 
18 #include <hitrace_meter.h>
19 #include <transaction/rs_transaction.h>
20 
21 #include "rs_adapter.h"
22 #include "window_manager_hilog.h"
23 #include <power_mgr_client.h>
24 
25 namespace OHOS::Rosen {
26 WM_IMPLEMENT_SINGLE_INSTANCE(MultiScreenPowerChangeManager)
27 namespace {
28 const ScreenId SCREEN_ID_FULL = 0;
29 } // namespace
30 
InitMultiScreenPowerChangeMap()31 void MultiScreenPowerChangeManager::InitMultiScreenPowerChangeMap()
32 {
33     if (handleScreenPowerChangeMap_.size() != 0) {
34         TLOGW(WmsLogTag::DMS, "multi screen power change map has init!");
35         return;
36     }
37     /* screen switch open */
38     handleScreenPowerChangeMap_[MultiScreenPowerSwitchType::SCREEN_SWITCH_ON] =
39         [this](sptr<ScreenSession>& innerScreen, sptr<ScreenSession>& externalScreen) {
40             return HandleScreenOnChange(innerScreen, externalScreen);
41         };
42     /* screen switch close */
43     handleScreenPowerChangeMap_[MultiScreenPowerSwitchType::SCREEN_SWITCH_OFF] =
44         [this](sptr<ScreenSession>& innerScreen, sptr<ScreenSession>& externalScreen) {
45         return HandleScreenOffChange(innerScreen, externalScreen);
46     };
47     /* setting switch external screen */
48     handleScreenPowerChangeMap_[MultiScreenPowerSwitchType::SCREEN_SWITCH_EXTERNAL] =
49         [this](sptr<ScreenSession>& innerScreen, sptr<ScreenSession>& externalScreen) {
50         return HandleScreenOnlyExternalModeChange(innerScreen, externalScreen);
51     };
52 }
53 
OnMultiScreenPowerChangeRequest(sptr<ScreenSession> & innerScreen,sptr<ScreenSession> & externalScreen,MultiScreenPowerSwitchType switchStatus)54 DMError MultiScreenPowerChangeManager::OnMultiScreenPowerChangeRequest(sptr<ScreenSession>& innerScreen,
55     sptr<ScreenSession>& externalScreen, MultiScreenPowerSwitchType switchStatus)
56 {
57     DMError handleRet = DMError::DM_OK;
58     if (innerScreen == nullptr || externalScreen == nullptr) {
59         TLOGE(WmsLogTag::DMS, "parameters nullptr.");
60         return DMError::DM_ERROR_NULLPTR;
61     }
62     auto handleCall = handleScreenPowerChangeMap_.find(switchStatus);
63     if (handleCall != handleScreenPowerChangeMap_.end() && handleCall->second != nullptr) {
64         auto powerHandleFunction = handleCall->second;
65         handleRet = powerHandleFunction(innerScreen, externalScreen);
66     } else {
67         TLOGE(WmsLogTag::DMS, "failed to find function handler!");
68         handleRet = DMError::DM_ERROR_INVALID_CALLING;
69     }
70     return handleRet;
71 }
72 
HandleScreenOnChange(sptr<ScreenSession> & innerScreen,sptr<ScreenSession> & externalScreen)73 DMError MultiScreenPowerChangeManager::HandleScreenOnChange(sptr<ScreenSession>& innerScreen,
74     sptr<ScreenSession>& externalScreen)
75 {
76     if (innerScreen == nullptr || externalScreen == nullptr) {
77         TLOGE(WmsLogTag::DMS, "parameters nullptr.");
78         return DMError::DM_ERROR_NULLPTR;
79     }
80     std::ostringstream oss;
81     oss << "inner screenId: " << innerScreen->GetScreenId()
82         << ", rsId: " << innerScreen->GetRSScreenId()
83         << ", isExtend: " << (innerScreen->GetIsExtend() ? "true" : "false")
84         << ", externalScreen screenId: " << externalScreen->GetScreenId()
85         << ", rsId: " << externalScreen->GetRSScreenId()
86         << ", isExtend: " << (externalScreen->GetIsExtend() ? "true" : "false");
87     oss << std::endl;
88     TLOGW(WmsLogTag::DMS, "%{public}s", oss.str().c_str());
89     return OnRecoveryScreenModeByPowerChange(innerScreen, externalScreen);
90 }
91 
HandleScreenOffChange(sptr<ScreenSession> & innerScreen,sptr<ScreenSession> & externalScreen)92 DMError MultiScreenPowerChangeManager::HandleScreenOffChange(sptr<ScreenSession>& innerScreen,
93     sptr<ScreenSession>& externalScreen)
94 {
95     if (innerScreen == nullptr || externalScreen == nullptr) {
96         TLOGE(WmsLogTag::DMS, "parameters nullptr.");
97         return DMError::DM_ERROR_NULLPTR;
98     }
99     innerCombination_ = innerScreen->GetScreenCombination();
100     externalCombination_ = externalScreen->GetScreenCombination();
101 
102     std::ostringstream oss;
103     oss << "inner screenId: " << innerScreen->GetScreenId()
104         << ", rsId: " << innerScreen->GetRSScreenId()
105         << ", combination: " << static_cast<int32_t>(innerCombination_)
106         << ", externalScreen screenId: " << externalScreen->GetScreenId()
107         << ", rsId: " << externalScreen->GetRSScreenId()
108         << ", combination: " << static_cast<int32_t>(externalCombination_);
109     oss << std::endl;
110     TLOGW(WmsLogTag::DMS, "%{public}s", oss.str().c_str());
111     return HandleScreenOnlyExternalModeChange(innerScreen, externalScreen);
112 }
113 
InitRecoveryMultiScreenModeChangeMap()114 void MultiScreenPowerChangeManager::InitRecoveryMultiScreenModeChangeMap()
115 {
116     if (handleRecoveryScreenModeChangeMap_.size() != 0) {
117         TLOGW(WmsLogTag::DMS, "recovery multi screen mode change map has init!");
118         return;
119     }
120     /* recovery inner main and external extend change from external main. */
121     handleRecoveryScreenModeChangeMap_[{ ScreenCombination::SCREEN_MAIN, ScreenCombination::SCREEN_EXTEND}] =
122         [this](sptr<ScreenSession>& innerScreen, sptr<ScreenSession>& externalScreen) {
123             return HandleRecoveryInnerMainExternalExtendChange(innerScreen, externalScreen);
124         };
125     /* recovery inner main and external mirror change from external main. */
126     handleRecoveryScreenModeChangeMap_[{ ScreenCombination::SCREEN_MIRROR, ScreenCombination::SCREEN_MAIN }] =
127         [this](sptr<ScreenSession>& innerScreen, sptr<ScreenSession>& externalScreen) {
128             return HandleRecoveryInnerMirrorExternalMainChange(innerScreen, externalScreen);
129         };
130     /* recovery inner extend and external main change from external main. */
131     handleRecoveryScreenModeChangeMap_[{ ScreenCombination::SCREEN_EXTEND, ScreenCombination::SCREEN_MAIN}] =
132         [this](sptr<ScreenSession>& innerScreen, sptr<ScreenSession>& externalScreen) {
133             return HandleRecoveryInnerExtendExternalMainChange(innerScreen, externalScreen);
134         };
135     /* recovery inner mirror and external main change from external main. */
136     handleRecoveryScreenModeChangeMap_[{ ScreenCombination::SCREEN_MAIN, ScreenCombination::SCREEN_MIRROR}] =
137         [this](sptr<ScreenSession>& innerScreen, sptr<ScreenSession>& externalScreen) {
138             return HandleRecoveryInnerMainExternalMirrorChange(innerScreen, externalScreen);
139         };
140 }
141 
InitMultiScreenModeOffChangeMap()142 void MultiScreenPowerChangeManager::InitMultiScreenModeOffChangeMap()
143 {
144     if (handleScreenOffModeChangeMap_.size() != 0) {
145         TLOGW(WmsLogTag::DMS, "multi screen mode change map has init!");
146         return;
147     }
148     /* form inner main and external extend change to external main. */
149     handleScreenOffModeChangeMap_[{ ScreenCombination::SCREEN_MAIN, ScreenCombination::SCREEN_EXTEND}] =
150         [this](sptr<ScreenSession>& innerScreen, sptr<ScreenSession>& externalScreen) {
151             return HandleInnerMainExternalExtendChange(innerScreen, externalScreen);
152         };
153     /* form inner main and external mirror change to external main. */
154     handleScreenOffModeChangeMap_[{ ScreenCombination::SCREEN_MAIN, ScreenCombination::SCREEN_MIRROR}] =
155         [this](sptr<ScreenSession>& innerScreen, sptr<ScreenSession>& externalScreen) {
156             return HandleInnerMainExternalMirrorChange(innerScreen, externalScreen);
157         };
158     /* form inner extend and external main change to external main. */
159     handleScreenOffModeChangeMap_[{ ScreenCombination::SCREEN_EXTEND, ScreenCombination::SCREEN_MAIN}] =
160         [this](sptr<ScreenSession>& innerScreen, sptr<ScreenSession>& externalScreen) {
161             return HandleInnerExtendExternalMainChange(innerScreen, externalScreen);
162         };
163     /* form inner mirror and external main change to external main. */
164     handleScreenOffModeChangeMap_[{ ScreenCombination::SCREEN_MIRROR, ScreenCombination::SCREEN_MAIN }] =
165         [this](sptr<ScreenSession>& innerScreen, sptr<ScreenSession>& externalScreen) {
166             return HandleInnerMirrorExternalMainChange(innerScreen, externalScreen);
167         };
168 }
169 
HandleScreenOnlyExternalModeChange(sptr<ScreenSession> & innerScreen,sptr<ScreenSession> & externalScreen)170 DMError MultiScreenPowerChangeManager::HandleScreenOnlyExternalModeChange(sptr<ScreenSession>& innerScreen,
171     sptr<ScreenSession>& externalScreen)
172 {
173     DMError handleRet = DMError::DM_OK;
174     if (innerScreen == nullptr || externalScreen == nullptr) {
175         TLOGE(WmsLogTag::DMS, "parameters nullptr.");
176         return DMError::DM_ERROR_NULLPTR;
177     }
178     ScreenCombination innerCombination = innerScreen->GetScreenCombination();
179     ScreenCombination externalCombination = externalScreen->GetScreenCombination();
180     auto modeHandleCall = handleScreenOffModeChangeMap_.find({innerCombination, externalCombination});
181     if (modeHandleCall != handleScreenOffModeChangeMap_.end()) {
182         auto modeHandleFunction = modeHandleCall->second;
183         handleRet = modeHandleFunction(innerScreen, externalScreen);
184         MultiScreenChangeUtils::SetExternalScreenOffScreenRendering(innerScreen, externalScreen);
185     } else {
186         TLOGE(WmsLogTag::DMS, "failed to find function handler!");
187         handleRet = DMError::DM_ERROR_INVALID_CALLING;
188     }
189     return handleRet;
190 }
191 
ScreenDisplayNodeRemove(sptr<ScreenSession> & screenScreen)192 void MultiScreenPowerChangeManager::ScreenDisplayNodeRemove(sptr<ScreenSession>& screenScreen)
193 {
194     {
195         TLOGW(WmsLogTag::DMS, "removeNode screenId=%{public}" PRIu64, screenScreen->GetScreenId());
196         std::shared_ptr<RSDisplayNode> displayNode = screenScreen->GetDisplayNode();
197         if (displayNode != nullptr) {
198             ScreenSessionManager::GetInstance().SetScreenOffset(screenScreen->GetScreenId(), 0, 0);
199             displayNode->RemoveFromTree();
200             screenScreen->ReleaseDisplayNode();
201         }
202         displayNode = nullptr;
203     }
204     RSTransactionAdapter::FlushImplicitTransaction(screenScreen->GetRSUIContext());
205 }
206 
ScreenToExtendChange(sptr<IScreenSessionManagerClient> ssmClient,sptr<ScreenSession> screenSession)207 void MultiScreenPowerChangeManager::ScreenToExtendChange(sptr<IScreenSessionManagerClient> ssmClient,
208     sptr<ScreenSession> screenSession)
209 {
210     MultiScreenChangeUtils::CreateExtendSession(screenSession);
211 
212     MultiScreenChangeUtils::ScreenConnectionChange(ssmClient, screenSession, ScreenEvent::CONNECTED);
213     TLOGW(WmsLogTag::DMS, "screen to extend change end.");
214 }
215 
NotifyClientCreateSessionOnly(sptr<IScreenSessionManagerClient> ssmClient,sptr<ScreenSession> screenSession)216 void MultiScreenPowerChangeManager::NotifyClientCreateSessionOnly(sptr<IScreenSessionManagerClient> ssmClient,
217     sptr<ScreenSession> screenSession)
218 {
219     screenSession->SetScreenCombination(ScreenCombination::SCREEN_EXTEND);
220     ssmClient->OnCreateScreenSessionOnly(screenSession->GetScreenId(), screenSession->GetRSScreenId(),
221         screenSession->GetName(), true);
222     TLOGW(WmsLogTag::DMS, "notify client create session end.");
223 }
224 
CreateExternalScreenDisplayNodeOnly(sptr<ScreenSession> & innerScreen,sptr<ScreenSession> & externalScreen,ScreenCombination combination)225 void MultiScreenPowerChangeManager::CreateExternalScreenDisplayNodeOnly(sptr<ScreenSession>& innerScreen,
226     sptr<ScreenSession>& externalScreen, ScreenCombination combination)
227 {
228     TLOGW(WmsLogTag::DMS, "create extend screen rsId=%{public}" PRIu64, innerScreen->rsId_);
229     RSDisplayNodeConfig config = { innerScreen->rsId_, false, INVALID_NODEID};
230     if (combination == ScreenCombination::SCREEN_MIRROR) {
231         NodeId nodeId = externalScreen->GetDisplayNode() == nullptr ? 0 : externalScreen->GetDisplayNode()->GetId();
232         TLOGW(WmsLogTag::DMS, "config screen mirror displayNodeId=%{public}" PRIu64, nodeId);
233         config = { innerScreen->rsId_, true, nodeId };
234     }
235     innerScreen->ReuseDisplayNode(config);
236     TLOGW(WmsLogTag::DMS, "create screen displayNode end.");
237 }
238 
239 /* inner main and external extend to external main */
HandleInnerMainExternalExtendChange(sptr<ScreenSession> & innerScreen,sptr<ScreenSession> & externalScreen)240 DMError MultiScreenPowerChangeManager::HandleInnerMainExternalExtendChange(sptr<ScreenSession>& innerScreen,
241     sptr<ScreenSession>& externalScreen)
242 {
243     HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "%s", __func__);
244     sptr<IScreenSessionManagerClient> ssmClient = ScreenSessionManager::GetInstance().GetClientProxy();
245     if (ssmClient == nullptr) {
246         TLOGE(WmsLogTag::DMS, "client null");
247         return DMError::DM_ERROR_NULLPTR;
248     }
249     TLOGW(WmsLogTag::DMS, "inner main and external extend to external main start.");
250 
251     /* step1: change display Node */
252     MultiScreenChangeUtils::SetMultiScreenModeChangeTracker("InnerMainExternalExtendChange");
253     ScreenId innerScreenId = innerScreen->GetScreenId();
254     ScreenId externalScreenId = externalScreen->GetScreenId();
255     bool changeRet = ssmClient->OnExtendDisplayNodeChange(innerScreenId, externalScreenId);
256     if (!changeRet) {
257         TLOGE(WmsLogTag::DMS, "change displayNode failed.");
258         return DMError::DM_ERROR_REMOTE_CREATE_FAILED;
259     }
260 
261     /* step2: change combination */
262     MultiScreenChangeUtils::ScreenCombinationChange(innerScreen, externalScreen, ScreenCombination::SCREEN_EXTEND);
263 
264     /* step3: change physical screen info between inner and external screen */
265     MultiScreenChangeUtils::ScreenPhysicalInfoChange(innerScreen, externalScreen);
266 
267     /* step4: change position */
268     MultiScreenChangeUtils::ScreenMainPositionChange(externalScreen, innerScreen);
269 
270     /* step5: notify external screen property change */
271     MultiScreenChangeUtils::ScreenPropertyChangeNotify(innerScreen, externalScreen);
272 
273     /* step6: dpi change */
274     MultiScreenChangeUtils::ScreenDensityChangeNotify(innerScreen, externalScreen);
275 
276     /* step7: set inner screen unavailable */
277     MultiScreenChangeUtils::SetScreenAvailableStatus(externalScreen, false);
278 
279     /* step8: disconnect inner screen */
280     MultiScreenChangeUtils::ScreenConnectionChange(ssmClient, externalScreen, ScreenEvent::DISCONNECTED);
281 
282     /* step9: inner screen change */
283     ScreenSessionManager::GetInstance().CallRsSetScreenPowerStatusSync(externalScreen->GetRSScreenId(),
284         ScreenPowerStatus::POWER_STATUS_OFF);
285     CallRsSetScreenPowerStatusSyncToOn(innerScreen->GetRSScreenId());
286 
287     TLOGW(WmsLogTag::DMS, "inner main and external extend to external main end.");
288     return DMError::DM_OK;
289 }
290 
291 /* inner main and external mirror to external main */
HandleInnerMainExternalMirrorChange(sptr<ScreenSession> & innerScreen,sptr<ScreenSession> & externalScreen)292 DMError MultiScreenPowerChangeManager::HandleInnerMainExternalMirrorChange(sptr<ScreenSession>& innerScreen,
293     sptr<ScreenSession>& externalScreen)
294 {
295     HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "%s", __func__);
296     sptr<IScreenSessionManagerClient> ssmClient = ScreenSessionManager::GetInstance().GetClientProxy();
297     if (ssmClient == nullptr) {
298         TLOGE(WmsLogTag::DMS, "ssmClient null");
299         return DMError::DM_ERROR_NULLPTR;
300     }
301     MultiScreenChangeUtils::SetMultiScreenModeChangeTracker("InnerMainExternalMirrorChange");
302     TLOGW(WmsLogTag::DMS, "inner main and external mirror to external main start.");
303     std::ostringstream oss;
304     oss << "inner screenId: " << innerScreen->GetScreenId()
305         << ", rsId: " << innerScreen->GetRSScreenId()
306         << ", combination: " << static_cast<int32_t>(innerScreen->GetScreenCombination())
307         << ", externalScreen screenId: " << externalScreen->GetScreenId()
308         << ", rsId: " << externalScreen->GetRSScreenId()
309         << ", combination: " << static_cast<int32_t>(externalScreen->GetScreenCombination());
310     oss << std::endl;
311     TLOGW(WmsLogTag::DMS, "%{public}s", oss.str().c_str());
312 
313     /* step1: make sure client has extend session */
314     bool changeRet = ssmClient->OnMainDisplayNodeChange(innerScreen->GetScreenId(), externalScreen->GetScreenId(),
315         externalScreen->GetRSScreenId());
316     if (!changeRet) {
317         TLOGE(WmsLogTag::DMS, "main_extend OnMainDisplayNodeChange failed.");
318         return DMError::DM_ERROR_REMOTE_CREATE_FAILED;
319     }
320 
321     /* step2: set combination */
322     MultiScreenChangeUtils::ScreenCombinationChange(innerScreen, externalScreen, ScreenCombination::SCREEN_MIRROR);
323 
324     /* step3: change physical screen info between inner and external screen */
325     MultiScreenChangeUtils::ScreenPhysicalInfoChange(innerScreen, externalScreen);
326 
327     /* step4: change position */
328     MultiScreenChangeUtils::ScreenMainPositionChange(externalScreen, innerScreen);
329 
330     /* step5: notify external screen property change */
331     MultiScreenChangeUtils::ScreenPropertyChangeNotify(innerScreen, externalScreen);
332 
333     /* step6: dpi change */
334     MultiScreenChangeUtils::ScreenDensityChangeNotify(innerScreen, nullptr);
335 
336     /* step7: set screen unavailable */
337     MultiScreenChangeUtils::SetScreenAvailableStatus(externalScreen, false);
338 
339     /* step8: inner screen power change */
340     ScreenSessionManager::GetInstance().CallRsSetScreenPowerStatusSync(externalScreen->GetRSScreenId(),
341         ScreenPowerStatus::POWER_STATUS_OFF);
342     CallRsSetScreenPowerStatusSyncToOn(innerScreen->GetRSScreenId());
343     TLOGW(WmsLogTag::DMS, "inner main and external mirror to external main end.");
344     return DMError::DM_OK;
345 }
346 
347 /* inner extend and external main to external main */
HandleInnerExtendExternalMainChange(sptr<ScreenSession> & innerScreen,sptr<ScreenSession> & externalScreen)348 DMError MultiScreenPowerChangeManager::HandleInnerExtendExternalMainChange(sptr<ScreenSession>& innerScreen,
349     sptr<ScreenSession>& externalScreen)
350 {
351     sptr<IScreenSessionManagerClient> ssmClient = ScreenSessionManager::GetInstance().GetClientProxy();
352     if (ssmClient == nullptr) {
353         TLOGE(WmsLogTag::DMS, "ssmClient null");
354         return DMError::DM_ERROR_NULLPTR;
355     }
356     TLOGW(WmsLogTag::DMS, "inner extend and external main to external main start.");
357     MultiScreenChangeUtils::SetMultiScreenModeChangeTracker("InnerExtendExternalMainChange");
358 
359     /* step1: disconnect external screen */
360     HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "%s", __func__);
361     MultiScreenChangeUtils::ScreenConnectionChange(ssmClient, innerScreen, ScreenEvent::DISCONNECTED);
362 
363     /* step2: set screen combination */
364     MultiScreenChangeUtils::ScreenCombinationChange(externalScreen, innerScreen, ScreenCombination::SCREEN_EXTEND);
365 
366     /* step3: set screen unavailable */
367     MultiScreenChangeUtils::SetScreenAvailableStatus(innerScreen, false);
368 
369     /* step4: screen power change */
370     ScreenSessionManager::GetInstance().CallRsSetScreenPowerStatusSync(innerScreen->GetRSScreenId(),
371         ScreenPowerStatus::POWER_STATUS_OFF);
372     CallRsSetScreenPowerStatusSyncToOn(externalScreen->GetRSScreenId());
373     TLOGW(WmsLogTag::DMS, "inner extend and external main to external main end.");
374     return DMError::DM_OK;
375 }
376 
377 /* inner mirror and external main to external main */
HandleInnerMirrorExternalMainChange(sptr<ScreenSession> & innerScreen,sptr<ScreenSession> & externalScreen)378 DMError MultiScreenPowerChangeManager::HandleInnerMirrorExternalMainChange(sptr<ScreenSession>& innerScreen,
379     sptr<ScreenSession>& externalScreen)
380 {
381     HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "%s", __func__);
382     sptr<IScreenSessionManagerClient> ssmClient = ScreenSessionManager::GetInstance().GetClientProxy();
383     if (ssmClient == nullptr) {
384         TLOGE(WmsLogTag::DMS, "ssmClient null");
385         return DMError::DM_ERROR_NULLPTR;
386     }
387     TLOGW(WmsLogTag::DMS, "inner mirror and external main to external main start.");
388     MultiScreenChangeUtils::SetMultiScreenModeChangeTracker("InnerMirrorExternalMainChange");
389 
390     /* step1: notify client screen disconnect. */
391     MultiScreenChangeUtils::ScreenConnectionChange(ssmClient, innerScreen, ScreenEvent::DISCONNECTED);
392 
393     /* step2: set screen combination. */
394     MultiScreenChangeUtils::ScreenCombinationChange(externalScreen, innerScreen, ScreenCombination::SCREEN_MIRROR);
395 
396     /* step3: set inner screen unavailable. */
397     MultiScreenChangeUtils::SetScreenAvailableStatus(innerScreen, false);
398 
399     /* step4: remove inner screen displayNode. */
400     ScreenDisplayNodeRemove(innerScreen);
401 
402     /* step5: screen power change. */
403     ScreenSessionManager::GetInstance().CallRsSetScreenPowerStatusSync(innerScreen->GetRSScreenId(),
404         ScreenPowerStatus::POWER_STATUS_OFF);
405     CallRsSetScreenPowerStatusSyncToOn(externalScreen->GetRSScreenId());
406     TLOGW(WmsLogTag::DMS, "inner mirror and external main to external main end.");
407     return DMError::DM_OK;
408 }
409 
410 /* recovery external main to old status */
OnRecoveryScreenModeByPowerChange(sptr<ScreenSession> & innerScreen,sptr<ScreenSession> & externalScreen)411 DMError MultiScreenPowerChangeManager::OnRecoveryScreenModeByPowerChange(sptr<ScreenSession>& innerScreen,
412     sptr<ScreenSession>& externalScreen)
413 {
414     DMError handleRet = DMError::DM_OK;
415     if (innerScreen == nullptr || externalScreen == nullptr) {
416         TLOGE(WmsLogTag::DMS, "parameters nullptr.");
417         return DMError::DM_ERROR_NULLPTR;
418     }
419 
420     std::ostringstream oss;
421     oss << "inner screenId: " << innerScreen->GetScreenId()
422         << ", rsId: " << innerScreen->GetRSScreenId()
423         << ", innerCombination_: " << static_cast<int32_t>(innerCombination_)
424         << ", isInternal: " << (innerScreen->GetIsInternal() ? "true" : "false")
425         << ", externalScreen screenId: " << externalScreen->GetScreenId()
426         << ", rsId: " << externalScreen->GetRSScreenId()
427         << ", externalCombination_: " << static_cast<int32_t>(externalCombination_)
428         << ", isInternal: " << (externalScreen->GetIsInternal() ? "true" : "false");
429     oss << std::endl;
430     TLOGW(WmsLogTag::DMS, "%{public}s", oss.str().c_str());
431 
432     auto recoveryModeHandleCall = handleRecoveryScreenModeChangeMap_.find({innerCombination_, externalCombination_});
433     if (recoveryModeHandleCall != handleRecoveryScreenModeChangeMap_.end()) {
434         auto recoveryModeHandleFunction = recoveryModeHandleCall->second;
435         handleRet = recoveryModeHandleFunction(innerScreen, externalScreen);
436         MultiScreenChangeUtils::SetExternalScreenOffScreenRendering(innerScreen, externalScreen);
437     } else {
438         TLOGE(WmsLogTag::DMS, "failed to find recovery function handler!");
439         handleRet = DMError::DM_ERROR_INVALID_CALLING;
440     }
441     return handleRet;
442 }
443 
444 /* recovery external main to inner main and external extend by power on */
HandleRecoveryInnerMainExternalExtendChange(sptr<ScreenSession> & innerScreen,sptr<ScreenSession> & externalScreen)445 DMError MultiScreenPowerChangeManager::HandleRecoveryInnerMainExternalExtendChange(sptr<ScreenSession>& innerScreen,
446     sptr<ScreenSession>& externalScreen)
447 {
448     sptr<IScreenSessionManagerClient> ssmClient = ScreenSessionManager::GetInstance().GetClientProxy();
449     if (ssmClient == nullptr) {
450         TLOGE(WmsLogTag::DMS, "ssmClient null");
451         return DMError::DM_ERROR_NULLPTR;
452     }
453 
454     std::ostringstream oss;
455     oss << "inner screenId: " << innerScreen->GetScreenId()
456         << ", rsId: " << innerScreen->GetRSScreenId()
457         << ", innerCombination_: " << static_cast<int32_t>(innerCombination_)
458         << ", isInternal: " << (innerScreen->GetIsInternal() ? "true" : "false")
459         << ", externalScreen screenId: " << externalScreen->GetScreenId()
460         << ", rsId: " << externalScreen->GetRSScreenId()
461         << ", externalCombination_: " << static_cast<int32_t>(externalCombination_)
462         << ", isInternal: " << (externalScreen->GetIsInternal() ? "true" : "false");
463     oss << std::endl;
464     TLOGW(WmsLogTag::DMS, "%{public}s", oss.str().c_str());
465     MultiScreenChangeUtils::SetMultiScreenModeChangeTracker("RecoveryInnerMainExternalExtendChange");
466 
467     /* step1: create external screen mirror displayNode */
468     HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "%s", __func__);
469     CreateExternalScreenDisplayNodeOnly(innerScreen, externalScreen, ScreenCombination::SCREEN_EXTEND);
470     bool changeRet = ssmClient->OnCreateScreenSessionOnly(innerScreen->GetScreenId(), innerScreen->GetRSScreenId(),
471         innerScreen->GetName(), innerScreen->GetIsExtend());
472     if (!changeRet) {
473         TLOGE(WmsLogTag::DMS, "create screenSession failed.");
474         return DMError::DM_ERROR_REMOTE_CREATE_FAILED;
475     }
476 
477     /* step2: change display Node */
478     changeRet = ssmClient->OnExtendDisplayNodeChange(innerScreen->GetScreenId(), externalScreen->GetScreenId());
479     if (!changeRet) {
480         TLOGE(WmsLogTag::DMS, "extend displayNode change failed.");
481         return DMError::DM_ERROR_REMOTE_CREATE_FAILED;
482     }
483 
484     /* step3: change combination */
485     MultiScreenChangeUtils::ScreenCombinationChange(externalScreen, innerScreen, ScreenCombination::SCREEN_EXTEND);
486 
487     /* step4: change physical screen info between inner and external screen */
488     MultiScreenChangeUtils::ScreenPhysicalInfoChange(innerScreen, externalScreen);
489 
490     /* step5: notify extend change */
491     ScreenToExtendChange(ssmClient, innerScreen);
492 
493     /* step6: notify external screen property change */
494     MultiScreenChangeUtils::ScreenPropertyChangeNotify(innerScreen, externalScreen);
495 
496     /* step7: dpi change */
497     MultiScreenChangeUtils::ScreenDensityChangeNotify(innerScreen, nullptr);
498 
499     /* step8: change position */
500     MultiScreenChangeUtils::ScreenExtendPositionChange(innerScreen, externalScreen);
501 
502     /* step9: set screen unavailable */
503     MultiScreenChangeUtils::SetScreenAvailableStatus(innerScreen, true);
504 
505     /* step10: inner screen power on */
506     CallRsSetScreenPowerStatusSyncToOn(SCREEN_ID_FULL);
507     return DMError::DM_OK;
508 }
509 
510 /* recovery external main to inner main and external mirror */
HandleRecoveryInnerMainExternalMirrorChange(sptr<ScreenSession> & innerScreen,sptr<ScreenSession> & externalScreen)511 DMError MultiScreenPowerChangeManager::HandleRecoveryInnerMainExternalMirrorChange(sptr<ScreenSession>& innerScreen,
512     sptr<ScreenSession>& externalScreen)
513 {
514     std::ostringstream oss;
515     oss << "innerScreen screenId: " << innerScreen->GetScreenId()
516         << ", rsId: " << innerScreen->GetRSScreenId()
517         << ", externalScreen screenId: " << externalScreen->GetScreenId()
518         << ", rsId: " << externalScreen->GetRSScreenId();
519     oss << std::endl;
520     TLOGW(WmsLogTag::DMS, "%{public}s", oss.str().c_str());
521     MultiScreenChangeUtils::SetMultiScreenModeChangeTracker("RecoveryInnerMainExternalMirrorChange");
522 
523     /* step1: create external screen mirror displayNode */
524     HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "%s", __func__);
525     CreateExternalScreenDisplayNodeOnly(innerScreen, externalScreen, ScreenCombination::SCREEN_MIRROR);
526 
527     /* step2: make sure client has extend session */
528     sptr<IScreenSessionManagerClient> ssmClient = ScreenSessionManager::GetInstance().GetClientProxy();
529     if (ssmClient == nullptr) {
530         TLOGE(WmsLogTag::DMS, "ssmClient null");
531         return DMError::DM_ERROR_NULLPTR;
532     }
533     bool changeRet = ssmClient->OnMainDisplayNodeChange(externalScreen->GetScreenId(), innerScreen->GetScreenId(),
534         innerScreen->GetRSScreenId());
535     if (!changeRet) {
536         TLOGE(WmsLogTag::DMS, "call main displayNode change failed.");
537         return DMError::DM_ERROR_REMOTE_CREATE_FAILED;
538     }
539 
540     /* step3: set screen combination */
541     MultiScreenChangeUtils::ScreenCombinationChange(externalScreen, innerScreen, ScreenCombination::SCREEN_MIRROR);
542 
543     /* step4: change physical screen info between inner and external screen */
544     MultiScreenChangeUtils::ScreenPhysicalInfoChange(innerScreen, externalScreen);
545 
546     /* step5: change position */
547     MultiScreenChangeUtils::ScreenMainPositionChange(externalScreen, innerScreen);
548 
549     /* step6: notify external screen property change */
550     MultiScreenChangeUtils::ScreenPropertyChangeNotify(innerScreen, externalScreen);
551 
552     /* step7: dpi change */
553     MultiScreenChangeUtils::ScreenDensityChangeNotify(innerScreen, nullptr);
554 
555     /* step8: set screen unavailable */
556     MultiScreenChangeUtils::SetScreenAvailableStatus(innerScreen, true);
557 
558     /* step9: inner screen power on */
559     CallRsSetScreenPowerStatusSyncToOn(SCREEN_ID_FULL);
560     TLOGW(WmsLogTag::DMS, "recovery external main to inner main and external mirror end.");
561     return DMError::DM_OK;
562 }
563 
564 /* recovery external main to inner extend and external main */
HandleRecoveryInnerExtendExternalMainChange(sptr<ScreenSession> & innerScreen,sptr<ScreenSession> & externalScreen)565 DMError MultiScreenPowerChangeManager::HandleRecoveryInnerExtendExternalMainChange(sptr<ScreenSession>& innerScreen,
566     sptr<ScreenSession>& externalScreen)
567 {
568     sptr<IScreenSessionManagerClient> ssmClient = ScreenSessionManager::GetInstance().GetClientProxy();
569     if (ssmClient == nullptr) {
570         TLOGE(WmsLogTag::DMS, "ssmClient null");
571         return DMError::DM_ERROR_NULLPTR;
572     }
573     TLOGW(WmsLogTag::DMS, "recovery external main to inner extend and external main start.");
574     MultiScreenChangeUtils::SetMultiScreenModeChangeTracker("RecoveryInnerExtendExternalMainChange");
575 
576     /* step1: create external screen extend displayNode */
577     HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "%s", __func__);
578     CreateExternalScreenDisplayNodeOnly(innerScreen, externalScreen, ScreenCombination::SCREEN_EXTEND);
579     bool changeRet = ssmClient->OnCreateScreenSessionOnly(innerScreen->GetScreenId(), innerScreen->GetRSScreenId(),
580         innerScreen->GetName(), innerScreen->GetIsExtend());
581     if (!changeRet) {
582         TLOGE(WmsLogTag::DMS, "create screenSession failed.");
583         return DMError::DM_ERROR_REMOTE_CREATE_FAILED;
584     }
585 
586     /* step2: change screen combination */
587     MultiScreenChangeUtils::ScreenCombinationChange(externalScreen, innerScreen, ScreenCombination::SCREEN_EXTEND);
588 
589     /* step3: change position. */
590     MultiScreenChangeUtils::ScreenExtendPositionChange(externalScreen, innerScreen);
591 
592     /* step4: set screen unavailable. */
593     MultiScreenChangeUtils::SetScreenAvailableStatus(innerScreen, true);
594 
595     /* step5: change screen to extend. */
596     ScreenToExtendChange(ssmClient, innerScreen);
597 
598     /* step6: inner screen power on */
599     CallRsSetScreenPowerStatusSyncToOn(SCREEN_ID_FULL);
600     TLOGW(WmsLogTag::DMS, "recovery external main to inner extend and external main end.");
601     return DMError::DM_OK;
602 }
603 
604 /* recovery external main to inner mirror and external main */
HandleRecoveryInnerMirrorExternalMainChange(sptr<ScreenSession> & innerScreen,sptr<ScreenSession> & externalScreen)605 DMError MultiScreenPowerChangeManager::HandleRecoveryInnerMirrorExternalMainChange(sptr<ScreenSession>& innerScreen,
606     sptr<ScreenSession>& externalScreen)
607 {
608     /* step1: create inner screen mirror displayNode */
609     HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "%s", __func__);
610     MultiScreenChangeUtils::SetMultiScreenModeChangeTracker("RecoveryInnerMirrorExternalMainChange");
611     TLOGW(WmsLogTag::DMS, "recovery external main to inner mirror and external main start.");
612     CreateExternalScreenDisplayNodeOnly(innerScreen, externalScreen, ScreenCombination::SCREEN_MIRROR);
613 
614     /* step2: set screen combination */
615     MultiScreenChangeUtils::ScreenCombinationChange(externalScreen, innerScreen, ScreenCombination::SCREEN_MIRROR);
616 
617     /* step3: set inner screen unavailable */
618     MultiScreenChangeUtils::SetScreenAvailableStatus(innerScreen, true);
619 
620     /* step4: inner screen power on */
621     CallRsSetScreenPowerStatusSyncToOn(SCREEN_ID_FULL);
622     TLOGW(WmsLogTag::DMS, "recovery external main to inner mirror and external main end.");
623 
624     return DMError::DM_OK;
625 }
626 
SetInnerAndExternalCombination(ScreenCombination innerCombination,ScreenCombination externalCombination)627 void MultiScreenPowerChangeManager::SetInnerAndExternalCombination(ScreenCombination innerCombination,
628     ScreenCombination externalCombination)
629 {
630     innerCombination_ = innerCombination;
631     externalCombination_ = externalCombination;
632 }
633 
CallRsSetScreenPowerStatusSyncToOn(ScreenId screenId)634 void MultiScreenPowerChangeManager::CallRsSetScreenPowerStatusSyncToOn(ScreenId screenId)
635 {
636     if (!PowerMgr::PowerMgrClient::GetInstance().IsScreenOn() &&
637             ScreenSessionManager::GetInstance().IsSystemSleep()) {
638         TLOGI(WmsLogTag::DMS, "power state IsScreenOn is false");
639         return;
640     }
641 
642     if (!ScreenSessionManager::GetInstance().IsLapTopLidOpen() && screenId == SCREEN_ID_FULL) {
643         TLOGI(WmsLogTag::DMS, "laptop lid is close and build-in screen");
644         return;
645     }
646     ScreenSessionManager::GetInstance().CallRsSetScreenPowerStatusSync(screenId,
647         ScreenPowerStatus::POWER_STATUS_ON);
648 }
649 
MultiScreenPowerChangeManager()650 MultiScreenPowerChangeManager::MultiScreenPowerChangeManager()
651 {
652     /* init screen power change map */
653     InitMultiScreenPowerChangeMap();
654 
655     /* init screen off change map */
656     InitMultiScreenModeOffChangeMap();
657 
658     /* init recovery screen mode map */
659     InitRecoveryMultiScreenModeChangeMap();
660     TLOGW(WmsLogTag::DMS, "init multi screen power change map.");
661 }
662 
~MultiScreenPowerChangeManager()663 MultiScreenPowerChangeManager::~MultiScreenPowerChangeManager()
664 {
665     handleScreenPowerChangeMap_.clear();
666     handleRecoveryScreenModeChangeMap_.clear();
667     handleScreenOffModeChangeMap_.clear();
668     TLOGW(WmsLogTag::DMS, "destructor");
669 }
670 } // namespace OHOS::Rosen
671