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