1 /*
2 * Copyright (c) 2021-2022 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 "window_root.h"
17 #include <ability_manager_client.h>
18 #include <cinttypes>
19 #include <display_power_mgr_client.h>
20 #include <hisysevent.h>
21 #include <hitrace_meter.h>
22 #include <transaction/rs_transaction.h>
23
24 #include "display_manager_service_inner.h"
25 #include "window_helper.h"
26 #include "window_inner_manager.h"
27 #include "window_manager_hilog.h"
28 #include "window_manager_service.h"
29 #include "window_manager_agent_controller.h"
30 #include "permission.h"
31
32 namespace OHOS {
33 namespace Rosen {
34 namespace {
35 constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowRoot"};
36 }
37
GetTotalWindowNum() const38 uint32_t WindowRoot::GetTotalWindowNum() const
39 {
40 return static_cast<uint32_t>(windowNodeMap_.size());
41 }
42
GetWindowForDumpAceHelpInfo() const43 sptr<WindowNode> WindowRoot::GetWindowForDumpAceHelpInfo() const
44 {
45 for (auto& iter : windowNodeMap_) {
46 if (iter.second->GetWindowType() == WindowType::WINDOW_TYPE_DESKTOP ||
47 iter.second->GetWindowType() == WindowType::WINDOW_TYPE_NAVIGATION_BAR ||
48 iter.second->GetWindowType() == WindowType::WINDOW_TYPE_STATUS_BAR ||
49 iter.second->GetWindowType() == WindowType::WINDOW_TYPE_KEYGUARD) {
50 return iter.second;
51 }
52 }
53 return nullptr;
54 }
55
GetScreenGroupId(DisplayId displayId,bool & isRecordedDisplay)56 ScreenId WindowRoot::GetScreenGroupId(DisplayId displayId, bool& isRecordedDisplay)
57 {
58 for (auto iter : displayIdMap_) {
59 auto displayIdVec = iter.second;
60 if (std::find(displayIdVec.begin(), displayIdVec.end(), displayId) != displayIdVec.end()) {
61 isRecordedDisplay = true;
62 return iter.first;
63 }
64 }
65 isRecordedDisplay = false;
66 WLOGFE("Current display is not be recorded, displayId: %{public}" PRIu64 "", displayId);
67 return DisplayManagerServiceInner::GetInstance().GetScreenGroupIdByDisplayId(displayId);
68 }
69
GetOrCreateWindowNodeContainer(DisplayId displayId)70 sptr<WindowNodeContainer> WindowRoot::GetOrCreateWindowNodeContainer(DisplayId displayId)
71 {
72 auto container = GetWindowNodeContainer(displayId);
73 if (container != nullptr) {
74 return container;
75 }
76
77 // In case of have no container for default display, create container
78 WLOGFD("Create container for current display, displayId: %{public}" PRIu64 "", displayId);
79 sptr<DisplayInfo> displayInfo = DisplayManagerServiceInner::GetInstance().GetDisplayById(displayId);
80 return CreateWindowNodeContainer(displayInfo);
81 }
82
GetWindowNodeContainer(DisplayId displayId)83 sptr<WindowNodeContainer> WindowRoot::GetWindowNodeContainer(DisplayId displayId)
84 {
85 bool isRecordedDisplay;
86 ScreenId displayGroupId = GetScreenGroupId(displayId, isRecordedDisplay);
87 auto iter = windowNodeContainerMap_.find(displayGroupId);
88 if (iter != windowNodeContainerMap_.end()) {
89 // if container exist for screenGroup and display is not be recorded, process expand display
90 if (!isRecordedDisplay) {
91 sptr<DisplayInfo> displayInfo = DisplayManagerServiceInner::GetInstance().GetDisplayById(displayId);
92 // add displayId in displayId vector
93 displayIdMap_[displayGroupId].push_back(displayId);
94 auto displayRectMap = GetAllDisplayRectsByDMS(displayInfo);
95 DisplayId defaultDisplayId = DisplayManagerServiceInner::GetInstance().GetDefaultDisplayId();
96 ProcessExpandDisplayCreate(defaultDisplayId, displayInfo, displayRectMap);
97 }
98 return iter->second;
99 }
100 return nullptr;
101 }
102
CreateWindowNodeContainer(sptr<DisplayInfo> displayInfo)103 sptr<WindowNodeContainer> WindowRoot::CreateWindowNodeContainer(sptr<DisplayInfo> displayInfo)
104 {
105 if (displayInfo == nullptr || !CheckDisplayInfo(displayInfo)) {
106 WLOGFE("get display failed or get invalid display info");
107 return nullptr;
108 }
109
110 DisplayId displayId = displayInfo->GetDisplayId();
111 ScreenId displayGroupId = displayInfo->GetScreenGroupId();
112 WLOGFD("create new container for display, width: %{public}d, height: %{public}d, "
113 "displayGroupId:%{public}" PRIu64", displayId:%{public}" PRIu64"", displayInfo->GetWidth(),
114 displayInfo->GetHeight(), displayGroupId, displayId);
115 sptr<WindowNodeContainer> container = new WindowNodeContainer(displayInfo, displayGroupId);
116 windowNodeContainerMap_.insert(std::make_pair(displayGroupId, container));
117 std::vector<DisplayId> displayVec = { displayId };
118 displayIdMap_.insert(std::make_pair(displayGroupId, displayVec));
119 if (container == nullptr) {
120 WLOGFE("create container failed, displayId :%{public}" PRIu64 "", displayId);
121 return nullptr;
122 }
123 container->GetLayoutPolicy()->SetSplitRatioConfig(splitRatioConfig_);
124 return container;
125 }
126
CheckDisplayInfo(const sptr<DisplayInfo> & display)127 bool WindowRoot::CheckDisplayInfo(const sptr<DisplayInfo>& display)
128 {
129 const int32_t minWidth = 50;
130 const int32_t minHeight = 50;
131 const int32_t maxWidth = 7680;
132 const int32_t maxHeight = 7680; // 8k resolution
133 if (display->GetWidth() < minWidth || display->GetWidth() > maxWidth ||
134 display->GetHeight() < minHeight || display->GetHeight() > maxHeight) {
135 return false;
136 }
137 return true;
138 }
139
GetWindowNode(uint32_t windowId) const140 sptr<WindowNode> WindowRoot::GetWindowNode(uint32_t windowId) const
141 {
142 auto iter = windowNodeMap_.find(windowId);
143 if (iter == windowNodeMap_.end()) {
144 return nullptr;
145 }
146 return iter->second;
147 }
148
GetBackgroundNodesByScreenId(ScreenId screenGroupId,std::vector<sptr<WindowNode>> & windowNodes) const149 void WindowRoot::GetBackgroundNodesByScreenId(ScreenId screenGroupId, std::vector<sptr<WindowNode>>& windowNodes) const
150 {
151 for (const auto& it : windowNodeMap_) {
152 if (it.second && screenGroupId == DisplayManagerServiceInner::GetInstance().GetScreenGroupIdByDisplayId(
153 it.second->GetDisplayId()) && !it.second->currentVisibility_) {
154 windowNodes.push_back(it.second);
155 }
156 }
157 }
158
FindWindowNodeWithToken(const sptr<IRemoteObject> & token) const159 sptr<WindowNode> WindowRoot::FindWindowNodeWithToken(const sptr<IRemoteObject>& token) const
160 {
161 if (token == nullptr) {
162 WLOGFE("token is null");
163 return nullptr;
164 }
165 auto iter = std::find_if(windowNodeMap_.begin(), windowNodeMap_.end(),
166 [token](const std::map<uint32_t, sptr<WindowNode>>::value_type& pair) {
167 if (!(WindowHelper::IsSubWindow(pair.second->GetWindowType()))) {
168 return pair.second->abilityToken_ == token;
169 }
170 return false;
171 });
172 if (iter == windowNodeMap_.end()) {
173 WLOGFD("cannot find windowNode");
174 return nullptr;
175 }
176 return iter->second;
177 }
178
AddDeathRecipient(sptr<WindowNode> node)179 void WindowRoot::AddDeathRecipient(sptr<WindowNode> node)
180 {
181 if (node == nullptr) {
182 WLOGFE("AddDeathRecipient failed, node is nullptr");
183 return;
184 }
185 WLOGFD("Add for window: %{public}u", node->GetWindowId());
186
187 auto remoteObject = node->GetWindowToken()->AsObject();
188 windowIdMap_.insert(std::make_pair(remoteObject, node->GetWindowId()));
189
190 if (windowDeath_ == nullptr) {
191 WLOGFD("failed to create death Recipient ptr WindowDeathRecipient");
192 return;
193 }
194 if (!remoteObject->AddDeathRecipient(windowDeath_)) {
195 WLOGFD("failed to add death recipient");
196 }
197 }
198
SaveWindow(const sptr<WindowNode> & node)199 WMError WindowRoot::SaveWindow(const sptr<WindowNode>& node)
200 {
201 if (node == nullptr) {
202 WLOGFE("add window failed, node is nullptr");
203 return WMError::WM_ERROR_NULLPTR;
204 }
205
206 WLOGFD("save windowId %{public}u", node->GetWindowId());
207 windowNodeMap_.insert(std::make_pair(node->GetWindowId(), node));
208 if (node->surfaceNode_ != nullptr) {
209 surfaceIdWindowNodeMap_.insert(std::make_pair(node->surfaceNode_->GetId(), node));
210 }
211 if (node->GetWindowToken()) {
212 AddDeathRecipient(node);
213 }
214 // Register FirstFrame Callback to rs, inform ability to get snapshot
215 wptr<WindowNode> weak = node;
216 auto firstFrameCompleteCallback = [weak]() {
217 auto weakNode = weak.promote();
218 if (weakNode == nullptr) {
219 WLOGFE("windowNode is nullptr");
220 return;
221 }
222 WindowInnerManager::GetInstance().CompleteFirstFrameDrawing(weakNode);
223 };
224 if (node->surfaceNode_ && WindowHelper::IsMainWindow(node->GetWindowType())) {
225 node->surfaceNode_->SetBufferAvailableCallback(firstFrameCompleteCallback);
226 }
227 return WMError::WM_OK;
228 }
229
MinimizeStructuredAppWindowsExceptSelf(sptr<WindowNode> & node)230 WMError WindowRoot::MinimizeStructuredAppWindowsExceptSelf(sptr<WindowNode>& node)
231 {
232 HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "root:MinimizeStructuredAppWindowsExceptSelf");
233 auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId());
234 if (container == nullptr) {
235 WLOGFE("MinimizeAbility failed, window container could not be found");
236 return WMError::WM_ERROR_NULLPTR;
237 }
238 return container->MinimizeStructuredAppWindowsExceptSelf(node);
239 }
240
MinimizeTargetWindows(std::vector<uint32_t> & windowIds)241 void WindowRoot::MinimizeTargetWindows(std::vector<uint32_t>& windowIds)
242 {
243 for (auto& windowId : windowIds) {
244 if (windowNodeMap_.count(windowId) != 0) {
245 auto windowNode = windowNodeMap_[windowId];
246 if (windowNode->GetWindowType() == WindowType::WINDOW_TYPE_APP_MAIN_WINDOW) {
247 MinimizeApp::AddNeedMinimizeApp(windowNode, MinimizeReason::GESTURE_ANIMATION);
248 } else {
249 WLOGFE("Minimize window failed id: %{public}u, type: %{public}u",
250 windowNode->GetWindowId(), static_cast<uint32_t>(windowNode->GetWindowType()));
251 }
252 }
253 }
254 }
255
GetSplitScreenWindowNodes(DisplayId displayId)256 std::vector<sptr<WindowNode>> WindowRoot::GetSplitScreenWindowNodes(DisplayId displayId)
257 {
258 auto container = GetOrCreateWindowNodeContainer(displayId);
259 if (container == nullptr) {
260 return {};
261 }
262 auto displayGroupController = container->GetMultiDisplayController();
263 if (displayGroupController == nullptr) {
264 return {};
265 }
266 auto windowPair = displayGroupController->GetWindowPairByDisplayId(displayId);
267 if (windowPair == nullptr) {
268 return {};
269 }
270 return windowPair->GetPairedWindows();
271 }
272
IsForbidDockSliceMove(DisplayId displayId) const273 bool WindowRoot::IsForbidDockSliceMove(DisplayId displayId) const
274 {
275 auto container = const_cast<WindowRoot*>(this)->GetOrCreateWindowNodeContainer(displayId);
276 if (container == nullptr) {
277 WLOGFE("can't find container");
278 return true;
279 }
280 return container->IsForbidDockSliceMove(displayId);
281 }
282
IsDockSliceInExitSplitModeArea(DisplayId displayId) const283 bool WindowRoot::IsDockSliceInExitSplitModeArea(DisplayId displayId) const
284 {
285 auto container = const_cast<WindowRoot*>(this)->GetOrCreateWindowNodeContainer(displayId);
286 if (container == nullptr) {
287 WLOGFE("can't find container");
288 return false;
289 }
290 return container->IsDockSliceInExitSplitModeArea(displayId);
291 }
292
ExitSplitMode(DisplayId displayId)293 void WindowRoot::ExitSplitMode(DisplayId displayId)
294 {
295 auto container = GetOrCreateWindowNodeContainer(displayId);
296 if (container == nullptr) {
297 WLOGFE("can't find container");
298 return;
299 }
300 container->ExitSplitMode(displayId);
301 }
302
AddSurfaceNodeIdWindowNodePair(uint64_t surfaceNodeId,sptr<WindowNode> node)303 void WindowRoot::AddSurfaceNodeIdWindowNodePair(uint64_t surfaceNodeId, sptr<WindowNode> node)
304 {
305 surfaceIdWindowNodeMap_.insert(std::make_pair(surfaceNodeId, node));
306 }
307
GetVisibilityWindowInfo(std::vector<sptr<WindowVisibilityInfo>> & infos) const308 void WindowRoot::GetVisibilityWindowInfo(std::vector<sptr<WindowVisibilityInfo>>& infos) const
309 {
310 if (!Permission::IsSystemCalling()) {
311 WLOGFE("Get Visible Window Permission Denied");
312 }
313 VisibleData& VisibleWindow = lastOcclusionData_->GetVisibleData();
314 for (auto surfaceId : VisibleWindow) {
315 auto iter = surfaceIdWindowNodeMap_.find(surfaceId);
316 if (iter == surfaceIdWindowNodeMap_.end()) {
317 continue;
318 }
319 sptr<WindowNode> node = iter->second;
320 if (node == nullptr) {
321 continue;
322 }
323 infos.emplace_back(new WindowVisibilityInfo(node->GetWindowId(), node->GetCallingPid(),
324 node->GetCallingUid(), true, node->GetWindowType()));
325 }
326 }
327
GetWindowVisibilityChangeInfo(std::shared_ptr<RSOcclusionData> occlusionData)328 std::vector<std::pair<uint64_t, bool>> WindowRoot::GetWindowVisibilityChangeInfo(
329 std::shared_ptr<RSOcclusionData> occlusionData)
330 {
331 std::vector<std::pair<uint64_t, bool>> visibilityChangeInfo;
332 VisibleData& currentVisibleWindow = occlusionData->GetVisibleData();
333 std::sort(currentVisibleWindow.begin(), currentVisibleWindow.end());
334 VisibleData& lastVisibleWindow = lastOcclusionData_->GetVisibleData();
335 uint32_t i, j;
336 i = j = 0;
337 for (; i < lastVisibleWindow.size() && j < currentVisibleWindow.size();) {
338 if (lastVisibleWindow[i] < currentVisibleWindow[j]) {
339 visibilityChangeInfo.emplace_back(lastVisibleWindow[i], false);
340 i++;
341 } else if (lastVisibleWindow[i] > currentVisibleWindow[j]) {
342 visibilityChangeInfo.emplace_back(currentVisibleWindow[j], true);
343 j++;
344 } else {
345 i++;
346 j++;
347 }
348 }
349 for (; i < lastVisibleWindow.size(); ++i) {
350 visibilityChangeInfo.emplace_back(lastVisibleWindow[i], false);
351 }
352 for (; j < currentVisibleWindow.size(); ++j) {
353 visibilityChangeInfo.emplace_back(currentVisibleWindow[j], true);
354 }
355 lastOcclusionData_ = occlusionData;
356 return visibilityChangeInfo;
357 }
358
NotifyWindowVisibilityChange(std::shared_ptr<RSOcclusionData> occlusionData)359 void WindowRoot::NotifyWindowVisibilityChange(std::shared_ptr<RSOcclusionData> occlusionData)
360 {
361 std::vector<std::pair<uint64_t, bool>> visibilityChangeInfo = GetWindowVisibilityChangeInfo(occlusionData);
362 std::vector<sptr<WindowVisibilityInfo>> windowVisibilityInfos;
363 bool hasAppWindowChange = false;
364 for (const auto& elem : visibilityChangeInfo) {
365 uint64_t surfaceId = elem.first;
366 bool isVisible = elem.second;
367 auto iter = surfaceIdWindowNodeMap_.find(surfaceId);
368 if (iter == surfaceIdWindowNodeMap_.end()) {
369 continue;
370 }
371 sptr<WindowNode> node = iter->second;
372 if (node == nullptr) {
373 continue;
374 }
375 node->isVisible_ = isVisible;
376 WindowType winType = node->GetWindowType();
377 hasAppWindowChange = (winType >= WindowType::APP_WINDOW_BASE && winType < WindowType::APP_WINDOW_END);
378 windowVisibilityInfos.emplace_back(new WindowVisibilityInfo(node->GetWindowId(), node->GetCallingPid(),
379 node->GetCallingUid(), isVisible, node->GetWindowType()));
380 WLOGFD("NotifyWindowVisibilityChange: covered status changed window:%{public}u, isVisible:%{public}d",
381 node->GetWindowId(), isVisible);
382 }
383 if (hasAppWindowChange) {
384 SwitchRenderModeIfNeeded();
385 }
386
387 if (windowVisibilityInfos.size() != 0) {
388 WindowManagerAgentController::GetInstance().UpdateWindowVisibilityInfo(windowVisibilityInfos);
389 }
390 }
391
GetAvoidAreaByType(uint32_t windowId,AvoidAreaType avoidAreaType)392 AvoidArea WindowRoot::GetAvoidAreaByType(uint32_t windowId, AvoidAreaType avoidAreaType)
393 {
394 AvoidArea avoidArea;
395 sptr<WindowNode> node = GetWindowNode(windowId);
396 if (node == nullptr) {
397 WLOGFE("could not find window");
398 return avoidArea;
399 }
400 sptr<WindowNodeContainer> container = GetOrCreateWindowNodeContainer(node->GetDisplayId());
401 if (container == nullptr) {
402 WLOGFE("add window failed, window container could not be found");
403 return avoidArea;
404 }
405 return container->GetAvoidAreaByType(node, avoidAreaType);
406 }
407
MinimizeAllAppWindows(DisplayId displayId)408 void WindowRoot::MinimizeAllAppWindows(DisplayId displayId)
409 {
410 auto container = GetOrCreateWindowNodeContainer(displayId);
411 if (container == nullptr) {
412 WLOGFE("can't find window node container, failed!");
413 return;
414 }
415 return container->MinimizeAllAppWindows(displayId);
416 }
417
ToggleShownStateForAllAppWindows()418 WMError WindowRoot::ToggleShownStateForAllAppWindows()
419 {
420 std::vector<DisplayId> displays = DisplayManagerServiceInner::GetInstance().GetAllDisplayIds();
421 std::vector<sptr<WindowNodeContainer>> containers;
422 bool isAllAppWindowsEmpty = true;
423 for (auto displayId : displays) {
424 auto container = GetOrCreateWindowNodeContainer(displayId);
425 if (container == nullptr) {
426 WLOGFE("can't find window node container, failed!");
427 continue;
428 }
429 containers.emplace_back(container);
430 isAllAppWindowsEmpty = isAllAppWindowsEmpty && container->IsAppWindowsEmpty();
431 }
432 WMError res = WMError::WM_OK;
433 std::for_each(containers.begin(), containers.end(),
434 [this, isAllAppWindowsEmpty, &res] (sptr<WindowNodeContainer> container) {
435 auto restoreFunc = [this](uint32_t windowId, WindowMode mode) {
436 auto windowNode = GetWindowNode(windowId);
437 if (windowNode == nullptr) {
438 return false;
439 }
440 if (!windowNode->GetWindowToken()) {
441 return false;
442 }
443 auto property = windowNode->GetWindowToken()->GetWindowProperty();
444 if (property == nullptr) {
445 return false;
446 }
447 if (mode == WindowMode::WINDOW_MODE_SPLIT_PRIMARY ||
448 mode == WindowMode::WINDOW_MODE_SPLIT_SECONDARY) {
449 property->SetWindowMode(mode);
450 windowNode->GetWindowToken()->RestoreSplitWindowMode(static_cast<uint32_t>(mode));
451 }
452 windowNode->GetWindowToken()->UpdateWindowState(WindowState::STATE_SHOWN);
453 WindowManagerService::GetInstance().AddWindow(property);
454 return true;
455 };
456 WMError tmpRes = tmpRes = container->ToggleShownStateForAllAppWindows(restoreFunc, isAllAppWindowsEmpty);
457 res = (res == WMError::WM_OK) ? tmpRes : res;
458 });
459 return res;
460 }
461
DestroyLeakStartingWindow()462 void WindowRoot::DestroyLeakStartingWindow()
463 {
464 WLOGFD("DestroyLeakStartingWindow is called");
465 std::vector<uint32_t> destroyIds;
466 for (auto& iter : windowNodeMap_) {
467 if (iter.second->startingWindowShown_ && !iter.second->GetWindowToken()) {
468 destroyIds.push_back(iter.second->GetWindowId());
469 }
470 }
471 for (auto& id : destroyIds) {
472 WLOGFD("Destroy Window id:%{public}u", id);
473 DestroyWindow(id, false);
474 }
475 }
476
PostProcessAddWindowNode(sptr<WindowNode> & node,sptr<WindowNode> & parentNode,sptr<WindowNodeContainer> & container)477 WMError WindowRoot::PostProcessAddWindowNode(sptr<WindowNode>& node, sptr<WindowNode>& parentNode,
478 sptr<WindowNodeContainer>& container)
479 {
480 if (!node->currentVisibility_) {
481 WLOGFD("window is invisible, do not need process");
482 return WMError::WM_DO_NOTHING;
483 }
484 if (WindowHelper::IsSubWindow(node->GetWindowType())) {
485 if (parentNode == nullptr) {
486 WLOGFE("window type is invalid");
487 return WMError::WM_ERROR_INVALID_TYPE;
488 }
489 sptr<WindowNode> parent = nullptr;
490 container->RaiseZOrderForAppWindow(parentNode, parent);
491 }
492 if (node->GetWindowProperty()->GetFocusable()) {
493 // when launcher reboot, the focus window should not change with showing a full screen window.
494 sptr<WindowNode> focusWin = GetWindowNode(container->GetFocusWindow());
495 if (focusWin == nullptr ||
496 !(WindowHelper::IsFullScreenWindow(focusWin->GetWindowMode()) && focusWin->zOrder_ > node->zOrder_)) {
497 container->SetFocusWindow(node->GetWindowId());
498 needCheckFocusWindow = true;
499 }
500 }
501 if (!WindowHelper::IsSystemBarWindow(node->GetWindowType())) {
502 container->SetActiveWindow(node->GetWindowId(), false);
503 }
504
505 for (auto& child : node->children_) {
506 if (child == nullptr || !child->currentVisibility_) {
507 break;
508 }
509 HandleKeepScreenOn(child->GetWindowId(), child->IsKeepScreenOn());
510 }
511 HandleKeepScreenOn(node->GetWindowId(), node->IsKeepScreenOn());
512 WLOGFD("windowId:%{public}u, name:%{public}s, orientation:%{public}u, type:%{public}u, isMainWindow:%{public}d",
513 node->GetWindowId(), node->GetWindowName().c_str(), static_cast<uint32_t>(node->GetRequestedOrientation()),
514 node->GetWindowType(), WindowHelper::IsMainWindow(node->GetWindowType()));
515 if (WindowHelper::IsRotatableWindow(node->GetWindowType(), node->GetWindowMode())) {
516 DisplayManagerServiceInner::GetInstance().
517 SetOrientationFromWindow(node->GetDisplayId(), node->GetRequestedOrientation());
518 }
519 return WMError::WM_OK;
520 }
521
NeedToStopAddingNode(sptr<WindowNode> & node,const sptr<WindowNodeContainer> & container)522 bool WindowRoot::NeedToStopAddingNode(sptr<WindowNode>& node, const sptr<WindowNodeContainer>& container)
523 {
524 if (!WindowHelper::IsMainWindow(node->GetWindowType())) {
525 return false;
526 }
527 // intercept the node which doesn't support floating mode at tile mode
528 if (WindowHelper::IsInvalidWindowInTileLayoutMode(node->GetModeSupportInfo(), container->GetCurrentLayoutMode())) {
529 WLOGFE("window doesn't support floating mode in tile, windowId: %{public}u", node->GetWindowId());
530 return true;
531 }
532 // intercept the node that the tile rect can't be applied to
533 WMError res = container->IsTileRectSatisfiedWithSizeLimits(node);
534 if (res != WMError::WM_OK) {
535 return true;
536 }
537 return false;
538 }
539
GetDisplayRectWithoutSystemBarAreas(DisplayId displayId)540 Rect WindowRoot::GetDisplayRectWithoutSystemBarAreas(DisplayId displayId)
541 {
542 std::map<WindowType, std::pair<bool, Rect>> systemBarRects;
543 for (const auto& it : windowNodeMap_) {
544 auto& node = it.second;
545 if (node && (node->GetDisplayId() == displayId) &&
546 WindowHelper::IsSystemBarWindow(node->GetWindowType())) {
547 systemBarRects[node->GetWindowType()] = std::make_pair(node->currentVisibility_, node->GetWindowRect());
548 }
549 }
550 auto container = GetOrCreateWindowNodeContainer(displayId);
551 if (container == nullptr) {
552 WLOGFE("GetDisplayRectWithoutSystemBarAreas failed, window container could not be found");
553 return {0, 0, 0, 0}; // empty rect
554 }
555 auto displayRect = container->GetDisplayRect(displayId);
556 Rect targetRect = displayRect;
557 bool isStatusShow = true;
558 if (systemBarRects.count(WindowType::WINDOW_TYPE_STATUS_BAR)) {
559 isStatusShow = systemBarRects[WindowType::WINDOW_TYPE_STATUS_BAR].first;
560 targetRect.posY_ = displayRect.posY_ + static_cast<int32_t>(
561 systemBarRects[WindowType::WINDOW_TYPE_STATUS_BAR].second.height_);
562 targetRect.height_ -= systemBarRects[WindowType::WINDOW_TYPE_STATUS_BAR].second.height_;
563 WLOGFD("after status bar winRect:[x:%{public}d, y:%{public}d, w:%{public}d, h:%{public}d]",
564 targetRect.posX_, targetRect.posY_, targetRect.width_, targetRect.height_);
565 }
566 if (systemBarRects.count(WindowType::WINDOW_TYPE_NAVIGATION_BAR)) {
567 if (isStatusShow && !(systemBarRects[WindowType::WINDOW_TYPE_NAVIGATION_BAR].first)) {
568 return targetRect;
569 }
570 targetRect.height_ -= systemBarRects[WindowType::WINDOW_TYPE_NAVIGATION_BAR].second.height_;
571 WLOGFD("after navi bar winRect:[x:%{public}d, y:%{public}d, w:%{public}d, h:%{public}d]",
572 targetRect.posX_, targetRect.posY_, targetRect.width_, targetRect.height_);
573 }
574 return targetRect;
575 }
576
GetAllAnimationPlayingNodes(std::vector<wptr<WindowNode>> & windowNodes)577 void WindowRoot::GetAllAnimationPlayingNodes(std::vector<wptr<WindowNode>>& windowNodes)
578 {
579 for (const auto& it : windowNodeMap_) {
580 if (it.second) {
581 if (!WindowHelper::IsMainWindow(it.second->GetWindowType())) {
582 continue;
583 }
584 WLOGFD("id:%{public}u state:%{public}u",
585 it.second->GetWindowId(), static_cast<uint32_t>(it.second->stateMachine_.GetCurrentState()));
586 if (it.second->stateMachine_.IsRemoteAnimationPlaying() ||
587 it.second->stateMachine_.GetAnimationCount() > 0) {
588 windowNodes.emplace_back(it.second);
589 }
590 }
591 }
592 }
593
LayoutWhenAddWindowNode(sptr<WindowNode> & node,bool afterAnimation)594 void WindowRoot::LayoutWhenAddWindowNode(sptr<WindowNode>& node, bool afterAnimation)
595 {
596 if (node == nullptr) {
597 WLOGFE("LayoutWhenAddWindowNode failed, node is nullptr");
598 return;
599 }
600 auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId());
601 if (container == nullptr) {
602 WLOGFE("add window failed, window container could not be found");
603 return;
604 }
605 container->LayoutWhenAddWindowNode(node, afterAnimation);
606 return;
607 }
608
AddWindowNode(uint32_t parentId,sptr<WindowNode> & node,bool fromStartingWin)609 WMError WindowRoot::AddWindowNode(uint32_t parentId, sptr<WindowNode>& node, bool fromStartingWin)
610 {
611 if (node == nullptr) {
612 WLOGFE("add window failed, node is nullptr");
613 return WMError::WM_ERROR_NULLPTR;
614 }
615
616 auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId());
617 if (container == nullptr) {
618 WLOGFE("add window failed, window container could not be found");
619 return WMError::WM_ERROR_NULLPTR;
620 }
621
622 if (NeedToStopAddingNode(node, container)) { // true means stop adding
623 return WMError::WM_ERROR_INVALID_WINDOW_MODE_OR_SIZE;
624 }
625
626 if (fromStartingWin) {
627 if (node->GetWindowMode() == WindowMode::WINDOW_MODE_FULLSCREEN &&
628 WindowHelper::IsAppWindow(node->GetWindowType()) && !node->isPlayAnimationShow_) {
629 container->NotifyDockWindowStateChanged(node, false);
630 WMError res = MinimizeStructuredAppWindowsExceptSelf(node);
631 if (res != WMError::WM_OK) {
632 WLOGFE("Minimize other structured window failed");
633 MinimizeApp::ClearNodesWithReason(MinimizeReason::OTHER_WINDOW);
634 return res;
635 }
636 }
637 WMError res = container->ShowStartingWindow(node);
638 if (res != WMError::WM_OK) {
639 MinimizeApp::ClearNodesWithReason(MinimizeReason::OTHER_WINDOW);
640 }
641 SwitchRenderModeIfNeeded();
642 return res;
643 }
644 // limit number of main window
645 uint32_t mainWindowNumber = container->GetWindowCountByType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW);
646 if (mainWindowNumber >= maxAppWindowNumber_ && node->GetWindowType() == WindowType::WINDOW_TYPE_APP_MAIN_WINDOW) {
647 container->MinimizeOldestAppWindow();
648 }
649
650 auto parentNode = GetWindowNode(parentId);
651
652 if (node->GetWindowType() == WindowType::WINDOW_TYPE_DIALOG) {
653 sptr<WindowNode> callerNode = FindDialogCallerNode(node->GetWindowType(), node->dialogTargetToken_);
654 parentNode = (callerNode != nullptr) ? callerNode : nullptr;
655 }
656
657 WMError res = container->AddWindowNode(node, parentNode);
658 if (res != WMError::WM_OK) {
659 WLOGFE("AddWindowNode failed with ret: %{public}u", static_cast<uint32_t>(res));
660 return res;
661 }
662 SwitchRenderModeIfNeeded();
663 return PostProcessAddWindowNode(node, parentNode, container);
664 }
665
RemoveWindowNode(uint32_t windowId,bool fromAnimation)666 WMError WindowRoot::RemoveWindowNode(uint32_t windowId, bool fromAnimation)
667 {
668 auto node = GetWindowNode(windowId);
669 if (node == nullptr) {
670 WLOGFE("could not find window");
671 return WMError::WM_ERROR_NULLPTR;
672 }
673 auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId());
674 if (container == nullptr) {
675 WLOGFE("remove window failed, window container could not be found");
676 return WMError::WM_ERROR_NULLPTR;
677 }
678 container->DropShowWhenLockedWindowIfNeeded(node);
679 UpdateFocusWindowWithWindowRemoved(node, container);
680 UpdateActiveWindowWithWindowRemoved(node, container);
681 UpdateBrightnessWithWindowRemoved(windowId, container);
682 WMError res = container->RemoveWindowNode(node, fromAnimation);
683 if (res == WMError::WM_OK) {
684 for (auto& child : node->children_) {
685 if (child == nullptr) {
686 break;
687 }
688 HandleKeepScreenOn(child->GetWindowId(), false);
689 }
690 HandleKeepScreenOn(windowId, false);
691 SwitchRenderModeIfNeeded();
692 }
693 auto nextRotatableWindow = container->GetNextRotatableWindow(windowId);
694 if (nextRotatableWindow != nullptr) {
695 DisplayManagerServiceInner::GetInstance().SetOrientationFromWindow(nextRotatableWindow->GetDisplayId(),
696 nextRotatableWindow->GetRequestedOrientation());
697 }
698 return res;
699 }
700
UpdateWindowNode(uint32_t windowId,WindowUpdateReason reason)701 WMError WindowRoot::UpdateWindowNode(uint32_t windowId, WindowUpdateReason reason)
702 {
703 auto node = GetWindowNode(windowId);
704 if (node == nullptr) {
705 WLOGFE("could not find window");
706 return WMError::WM_ERROR_NULLPTR;
707 }
708 auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId());
709 if (container == nullptr) {
710 WLOGFE("update window failed, window container could not be found");
711 return WMError::WM_ERROR_NULLPTR;
712 }
713 return container->UpdateWindowNode(node, reason);
714 }
715
UpdateSizeChangeReason(uint32_t windowId,WindowSizeChangeReason reason)716 WMError WindowRoot::UpdateSizeChangeReason(uint32_t windowId, WindowSizeChangeReason reason)
717 {
718 auto node = GetWindowNode(windowId);
719 if (node == nullptr) {
720 WLOGFE("could not find window");
721 return WMError::WM_ERROR_NULLPTR;
722 }
723 auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId());
724 if (container == nullptr) {
725 WLOGFE("update window size change reason failed, window container could not be found");
726 return WMError::WM_ERROR_NULLPTR;
727 }
728 container->UpdateSizeChangeReason(node, reason);
729 return WMError::WM_OK;
730 }
731
SetBrightness(uint32_t windowId,float brightness)732 void WindowRoot::SetBrightness(uint32_t windowId, float brightness)
733 {
734 auto node = GetWindowNode(windowId);
735 if (node == nullptr) {
736 WLOGFE("could not find window");
737 return;
738 }
739 auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId());
740 if (container == nullptr) {
741 WLOGFE("set brightness failed, window container could not be found");
742 return;
743 }
744 if (!WindowHelper::IsAppWindow(node->GetWindowType())) {
745 WLOGFD("non app window does not support set brightness");
746 return;
747 }
748 if (windowId == container->GetActiveWindow()) {
749 if (container->GetDisplayBrightness() != brightness) {
750 WLOGFD("set brightness with value: %{public}u", container->ToOverrideBrightness(brightness));
751 DisplayPowerMgr::DisplayPowerMgrClient::GetInstance().OverrideBrightness(
752 container->ToOverrideBrightness(brightness));
753 container->SetDisplayBrightness(brightness);
754 }
755 container->SetBrightnessWindow(windowId);
756 }
757 }
758
HandleKeepScreenOn(uint32_t windowId,bool requireLock)759 void WindowRoot::HandleKeepScreenOn(uint32_t windowId, bool requireLock)
760 {
761 auto node = GetWindowNode(windowId);
762 if (node == nullptr) {
763 WLOGFE("could not find window");
764 return;
765 }
766 auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId());
767 if (container == nullptr) {
768 WLOGFE("handle keep screen on failed, window container could not be found");
769 return;
770 }
771 container->HandleKeepScreenOn(node, requireLock);
772 }
773
UpdateFocusableProperty(uint32_t windowId)774 void WindowRoot::UpdateFocusableProperty(uint32_t windowId)
775 {
776 auto node = GetWindowNode(windowId);
777 if (node == nullptr) {
778 WLOGFE("could not find window");
779 return;
780 }
781 auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId());
782 if (container == nullptr) {
783 WLOGFE("handle focusable failed, window container could not be found");
784 return;
785 }
786
787 if (windowId != container->GetFocusWindow() || node->GetWindowProperty()->GetFocusable()) {
788 return;
789 }
790 auto nextFocusableWindow = container->GetNextFocusableWindow(windowId);
791 if (nextFocusableWindow != nullptr) {
792 WLOGFD("adjust focus window, next focus window id: %{public}u", nextFocusableWindow->GetWindowId());
793 container->SetFocusWindow(nextFocusableWindow->GetWindowId());
794 }
795 }
796
SetWindowMode(sptr<WindowNode> & node,WindowMode dstMode)797 WMError WindowRoot::SetWindowMode(sptr<WindowNode>& node, WindowMode dstMode)
798 {
799 auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId());
800 if (container == nullptr) {
801 WLOGFE("set window mode failed, window container could not be found");
802 return WMError::WM_ERROR_NULLPTR;
803 }
804 WindowMode curWinMode = node->GetWindowMode();
805 auto res = container->SetWindowMode(node, dstMode);
806 if (res == WMError::WM_OK
807 && (WindowHelper::IsSplitWindowMode(curWinMode) || WindowHelper::IsSplitWindowMode(dstMode))) {
808 WLOGFD("SwitchRender: split mode changed");
809 SwitchRenderModeIfNeeded();
810 }
811 if (WindowHelper::IsRotatableWindow(node->GetWindowType(), node->GetWindowMode())) {
812 DisplayManagerServiceInner::GetInstance().
813 SetOrientationFromWindow(node->GetDisplayId(), node->GetRequestedOrientation());
814 }
815 auto nextRotatableWindow = container->GetNextRotatableWindow(0);
816 if (nextRotatableWindow != nullptr) {
817 DisplayManagerServiceInner::GetInstance().SetOrientationFromWindow(nextRotatableWindow->GetDisplayId(),
818 nextRotatableWindow->GetRequestedOrientation());
819 }
820 return res;
821 }
822
DestroyWindowSelf(sptr<WindowNode> & node,const sptr<WindowNodeContainer> & container)823 WMError WindowRoot::DestroyWindowSelf(sptr<WindowNode>& node, const sptr<WindowNodeContainer>& container)
824 {
825 for (auto& child : node->children_) {
826 if (child == nullptr) {
827 continue;
828 }
829 child->parent_ = nullptr;
830 if ((child->GetWindowToken() != nullptr) && (child->abilityToken_ != node->abilityToken_) &&
831 (child->GetWindowType() == WindowType::WINDOW_TYPE_DIALOG)) {
832 child->GetWindowToken()->NotifyDestroy();
833 }
834 }
835 WMError res = container->RemoveWindowNode(node);
836 if (res != WMError::WM_OK) {
837 WLOGFE("RemoveWindowNode failed");
838 }
839 SwitchRenderModeIfNeeded();
840 return DestroyWindowInner(node);
841 }
842
DestroyWindowWithChild(sptr<WindowNode> & node,const sptr<WindowNodeContainer> & container)843 WMError WindowRoot::DestroyWindowWithChild(sptr<WindowNode>& node, const sptr<WindowNodeContainer>& container)
844 {
845 auto token = node->abilityToken_;
846 std::vector<uint32_t> windowIds;
847 WMError res = container->DestroyWindowNode(node, windowIds);
848 for (auto id : windowIds) {
849 node = GetWindowNode(id);
850 if (!node) {
851 continue;
852 }
853 HandleKeepScreenOn(id, false);
854 DestroyWindowInner(node);
855 if ((node->GetWindowToken() != nullptr) && (node->abilityToken_ != token) &&
856 (node->GetWindowType() == WindowType::WINDOW_TYPE_DIALOG)) {
857 node->GetWindowToken()->NotifyDestroy();
858 }
859 }
860 SwitchRenderModeIfNeeded();
861 return res;
862 }
863
DestroyWindow(uint32_t windowId,bool onlySelf)864 WMError WindowRoot::DestroyWindow(uint32_t windowId, bool onlySelf)
865 {
866 auto node = GetWindowNode(windowId);
867 if (node == nullptr) {
868 WLOGFE("destroy window failed, because window node is not exist.");
869 return WMError::WM_ERROR_NULLPTR;
870 }
871 WLOGFD("destroy window %{public}u, onlySelf:%{public}u.", windowId, onlySelf);
872 auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId());
873 if (!container) {
874 WLOGFW("destroy window failed, window container could not be found");
875 return DestroyWindowInner(node);
876 }
877
878 UpdateFocusWindowWithWindowRemoved(node, container);
879 UpdateActiveWindowWithWindowRemoved(node, container);
880 UpdateBrightnessWithWindowRemoved(windowId, container);
881 HandleKeepScreenOn(windowId, false);
882 if (onlySelf) {
883 return DestroyWindowSelf(node, container);
884 } else {
885 return DestroyWindowWithChild(node, container);
886 }
887 }
888
DestroyWindowInner(sptr<WindowNode> & node)889 WMError WindowRoot::DestroyWindowInner(sptr<WindowNode>& node)
890 {
891 if (node == nullptr) {
892 WLOGFE("window has been destroyed");
893 return WMError::WM_ERROR_DESTROYED_OBJECT;
894 }
895
896 if (node->isVisible_) {
897 std::vector<sptr<WindowVisibilityInfo>> windowVisibilityInfos;
898 node->isVisible_ = false;
899 windowVisibilityInfos.emplace_back(new WindowVisibilityInfo(node->GetWindowId(), node->GetCallingPid(),
900 node->GetCallingUid(), false, node->GetWindowType()));
901 WLOGFD("NotifyWindowVisibilityChange: covered status changed window:%{public}u, isVisible:%{public}d",
902 node->GetWindowId(), node->isVisible_);
903 WindowManagerAgentController::GetInstance().UpdateWindowVisibilityInfo(windowVisibilityInfos);
904 }
905
906 auto cmpFunc = [node](const std::map<uint64_t, sptr<WindowNode>>::value_type& pair) {
907 if (pair.second == nullptr) {
908 return false;
909 }
910 if (pair.second->GetWindowId() == node->GetWindowId()) {
911 return true;
912 }
913 return false;
914 };
915 auto iter = std::find_if(surfaceIdWindowNodeMap_.begin(), surfaceIdWindowNodeMap_.end(), cmpFunc);
916 if (iter != surfaceIdWindowNodeMap_.end()) {
917 surfaceIdWindowNodeMap_.erase(iter);
918 }
919
920 sptr<IWindow> window = node->GetWindowToken();
921 if ((window != nullptr) && (window->AsObject() != nullptr)) {
922 if (windowIdMap_.count(window->AsObject()) == 0) {
923 WLOGFD("window remote object has been destroyed");
924 return WMError::WM_ERROR_DESTROYED_OBJECT;
925 }
926
927 if (window->AsObject() != nullptr) {
928 window->AsObject()->RemoveDeathRecipient(windowDeath_);
929 }
930 windowIdMap_.erase(window->AsObject());
931 }
932 windowNodeMap_.erase(node->GetWindowId());
933 WLOGFD("destroy window node use_count:%{public}d", node->GetSptrRefCount());
934 return WMError::WM_OK;
935 }
936
UpdateFocusWindowWithWindowRemoved(const sptr<WindowNode> & node,const sptr<WindowNodeContainer> & container) const937 void WindowRoot::UpdateFocusWindowWithWindowRemoved(const sptr<WindowNode>& node,
938 const sptr<WindowNodeContainer>& container) const
939 {
940 if (node == nullptr || container == nullptr) {
941 WLOGFE("window is invalid");
942 return;
943 }
944 if (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) {
945 WLOGFD("window is divider, do not get next focus window.");
946 return;
947 }
948 uint32_t windowId = node->GetWindowId();
949 uint32_t focusedWindowId = container->GetFocusWindow();
950 WLOGFD("current window: %{public}u, focus window: %{public}u", windowId, focusedWindowId);
951 if (WindowHelper::IsMainWindow(node->GetWindowType())) {
952 if (windowId != focusedWindowId) {
953 auto iter = std::find_if(node->children_.begin(), node->children_.end(),
954 [focusedWindowId](sptr<WindowNode> node) {
955 return node->GetWindowId() == focusedWindowId;
956 });
957 if (iter == node->children_.end()) {
958 return;
959 }
960 }
961 if (!node->children_.empty()) {
962 auto firstChild = node->children_.front();
963 if (firstChild->priority_ < 0) {
964 windowId = firstChild->GetWindowId();
965 }
966 }
967 } else {
968 if (windowId != focusedWindowId) {
969 return;
970 }
971 }
972 auto nextFocusableWindow = container->GetNextFocusableWindow(windowId);
973 if (nextFocusableWindow != nullptr) {
974 WLOGFD("adjust focus window, next focus window id: %{public}u", nextFocusableWindow->GetWindowId());
975 container->SetFocusWindow(nextFocusableWindow->GetWindowId());
976 }
977 }
978
UpdateActiveWindowWithWindowRemoved(const sptr<WindowNode> & node,const sptr<WindowNodeContainer> & container) const979 void WindowRoot::UpdateActiveWindowWithWindowRemoved(const sptr<WindowNode>& node,
980 const sptr<WindowNodeContainer>& container) const
981 {
982 if (node == nullptr || container == nullptr) {
983 WLOGFE("window is invalid");
984 return;
985 }
986 uint32_t windowId = node->GetWindowId();
987 uint32_t activeWindowId = container->GetActiveWindow();
988 WLOGFD("current window: %{public}u, active window: %{public}u", windowId, activeWindowId);
989 if (WindowHelper::IsMainWindow(node->GetWindowType())) {
990 if (windowId != activeWindowId) {
991 auto iter = std::find_if(node->children_.begin(), node->children_.end(),
992 [activeWindowId](sptr<WindowNode> node) {
993 return node->GetWindowId() == activeWindowId;
994 });
995 if (iter == node->children_.end()) {
996 return;
997 }
998 }
999 if (!node->children_.empty()) {
1000 auto firstChild = node->children_.front();
1001 if (firstChild->priority_ < 0) {
1002 windowId = firstChild->GetWindowId();
1003 }
1004 }
1005 } else {
1006 if (windowId != activeWindowId) {
1007 return;
1008 }
1009 }
1010 auto nextActiveWindow = container->GetNextActiveWindow(windowId);
1011 if (nextActiveWindow != nullptr) {
1012 WLOGFD("adjust active window, next active window id: %{public}u", nextActiveWindow->GetWindowId());
1013 container->SetActiveWindow(nextActiveWindow->GetWindowId(), true);
1014 }
1015 }
1016
UpdateBrightnessWithWindowRemoved(uint32_t windowId,const sptr<WindowNodeContainer> & container) const1017 void WindowRoot::UpdateBrightnessWithWindowRemoved(uint32_t windowId, const sptr<WindowNodeContainer>& container) const
1018 {
1019 if (container == nullptr) {
1020 WLOGFE("window container could not be found");
1021 return;
1022 }
1023 if (windowId == container->GetBrightnessWindow()) {
1024 WLOGFD("adjust brightness window with active window: %{public}u", container->GetActiveWindow());
1025 container->UpdateBrightness(container->GetActiveWindow(), true);
1026 }
1027 }
1028
IsVerticalDisplay(sptr<WindowNode> & node) const1029 bool WindowRoot::IsVerticalDisplay(sptr<WindowNode>& node) const
1030 {
1031 auto container = const_cast<WindowRoot*>(this)->GetOrCreateWindowNodeContainer(node->GetDisplayId());
1032 if (container == nullptr) {
1033 WLOGFE("get display direction failed, window container could not be found");
1034 return false;
1035 }
1036 return container->IsVerticalDisplay(node->GetDisplayId());
1037 }
1038
RequestFocus(uint32_t windowId)1039 WMError WindowRoot::RequestFocus(uint32_t windowId)
1040 {
1041 auto node = GetWindowNode(windowId);
1042 if (node == nullptr) {
1043 WLOGFE("could not find window");
1044 return WMError::WM_ERROR_NULLPTR;
1045 }
1046 if (!node->currentVisibility_) {
1047 WLOGFE("could not request focus before it does not be shown");
1048 return WMError::WM_ERROR_INVALID_OPERATION;
1049 }
1050 auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId());
1051 if (container == nullptr) {
1052 WLOGFE("window container could not be found");
1053 return WMError::WM_ERROR_NULLPTR;
1054 }
1055 if (node->GetWindowProperty()->GetFocusable()) {
1056 return container->SetFocusWindow(windowId);
1057 }
1058 return WMError::WM_ERROR_INVALID_OPERATION;
1059 }
1060
RequestActiveWindow(uint32_t windowId)1061 WMError WindowRoot::RequestActiveWindow(uint32_t windowId)
1062 {
1063 auto node = GetWindowNode(windowId);
1064 if (node == nullptr) {
1065 WLOGFE("could not find window");
1066 return WMError::WM_ERROR_NULLPTR;
1067 }
1068 if (WindowHelper::IsSystemBarWindow(node->GetWindowType())) {
1069 WLOGFE("window could not be active window");
1070 return WMError::WM_ERROR_INVALID_TYPE;
1071 }
1072 auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId());
1073 if (container == nullptr) {
1074 WLOGFE("window container could not be found");
1075 return WMError::WM_ERROR_NULLPTR;
1076 }
1077 auto res = container->SetActiveWindow(windowId, false);
1078 WLOGFD("windowId:%{public}u, name:%{public}s, orientation:%{public}u, type:%{public}u, isMainWindow:%{public}d",
1079 windowId, node->GetWindowName().c_str(), static_cast<uint32_t>(node->GetRequestedOrientation()),
1080 node->GetWindowType(), WindowHelper::IsMainWindow(node->GetWindowType()));
1081 if (res == WMError::WM_OK &&
1082 WindowHelper::IsRotatableWindow(node->GetWindowType(), node->GetWindowMode())) {
1083 DisplayManagerServiceInner::GetInstance().
1084 SetOrientationFromWindow(node->GetDisplayId(), node->GetRequestedOrientation());
1085 }
1086 return res;
1087 }
1088
ProcessWindowStateChange(WindowState state,WindowStateChangeReason reason)1089 void WindowRoot::ProcessWindowStateChange(WindowState state, WindowStateChangeReason reason)
1090 {
1091 for (auto& elem : windowNodeContainerMap_) {
1092 if (elem.second == nullptr) {
1093 continue;
1094 }
1095 elem.second->ProcessWindowStateChange(state, reason);
1096 }
1097 }
1098
NotifySystemBarTints()1099 void WindowRoot::NotifySystemBarTints()
1100 {
1101 WLOGFD("notify current system bar tints");
1102 for (auto& it : windowNodeContainerMap_) {
1103 if (it.second != nullptr) {
1104 it.second->NotifySystemBarTints(displayIdMap_[it.first]);
1105 }
1106 }
1107 }
1108
RaiseZOrderForAppWindow(sptr<WindowNode> & node)1109 WMError WindowRoot::RaiseZOrderForAppWindow(sptr<WindowNode>& node)
1110 {
1111 if (node == nullptr) {
1112 WLOGFW("add window failed, node is nullptr");
1113 return WMError::WM_ERROR_NULLPTR;
1114 }
1115 if (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) {
1116 auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId());
1117 if (container == nullptr) {
1118 WLOGFW("window container could not be found");
1119 return WMError::WM_ERROR_NULLPTR;
1120 }
1121 container->RaiseSplitRelatedWindowToTop(node);
1122 return WMError::WM_OK;
1123 }
1124 if (node->GetWindowType() == WindowType::WINDOW_TYPE_DIALOG) {
1125 auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId());
1126 if (container == nullptr) {
1127 WLOGFW("window container could not be found");
1128 return WMError::WM_ERROR_NULLPTR;
1129 }
1130 sptr<WindowNode> parentNode = FindDialogCallerNode(node->GetWindowType(), node->dialogTargetToken_);
1131 if (parentNode != nullptr) {
1132 container->RaiseZOrderForAppWindow(node, parentNode);
1133 }
1134 return WMError::WM_OK;
1135 }
1136
1137 if (!WindowHelper::IsAppWindow(node->GetWindowType())) {
1138 WLOGFW("window is not app window");
1139 return WMError::WM_ERROR_INVALID_TYPE;
1140 }
1141 auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId());
1142 if (container == nullptr) {
1143 WLOGFW("add window failed, window container could not be found");
1144 return WMError::WM_ERROR_NULLPTR;
1145 }
1146
1147 auto parentNode = GetWindowNode(node->GetParentId());
1148 return container->RaiseZOrderForAppWindow(node, parentNode);
1149 }
1150
GetWindowIdByObject(const sptr<IRemoteObject> & remoteObject)1151 uint32_t WindowRoot::GetWindowIdByObject(const sptr<IRemoteObject>& remoteObject)
1152 {
1153 auto iter = windowIdMap_.find(remoteObject);
1154 return iter == std::end(windowIdMap_) ? INVALID_WINDOW_ID : iter->second;
1155 }
1156
OnRemoteDied(const sptr<IRemoteObject> & remoteObject)1157 void WindowRoot::OnRemoteDied(const sptr<IRemoteObject>& remoteObject)
1158 {
1159 callback_(Event::REMOTE_DIED, remoteObject);
1160 }
1161
GetTopWindowId(uint32_t mainWinId,uint32_t & topWinId)1162 WMError WindowRoot::GetTopWindowId(uint32_t mainWinId, uint32_t& topWinId)
1163 {
1164 if (windowNodeMap_.find(mainWinId) == windowNodeMap_.end()) {
1165 return WMError::WM_ERROR_INVALID_WINDOW;
1166 }
1167 auto node = windowNodeMap_[mainWinId];
1168 if (!node->currentVisibility_) {
1169 return WMError::WM_ERROR_INVALID_WINDOW;
1170 }
1171 if (!node->children_.empty()) {
1172 auto iter = node->children_.rbegin();
1173 if (WindowHelper::IsSubWindow((*iter)->GetWindowType()) ||
1174 WindowHelper::IsSystemSubWindow((*iter)->GetWindowType())) {
1175 topWinId = (*iter)->GetWindowId();
1176 return WMError::WM_OK;
1177 }
1178 }
1179 topWinId = mainWinId;
1180 return WMError::WM_OK;
1181 }
1182
SetWindowLayoutMode(DisplayId displayId,WindowLayoutMode mode)1183 WMError WindowRoot::SetWindowLayoutMode(DisplayId displayId, WindowLayoutMode mode)
1184 {
1185 auto container = GetOrCreateWindowNodeContainer(displayId);
1186 if (container == nullptr) {
1187 WLOGFE("window container could not be found");
1188 return WMError::WM_ERROR_NULLPTR;
1189 }
1190 WMError ret = container->SwitchLayoutPolicy(mode, displayId, true);
1191 if (ret != WMError::WM_OK) {
1192 WLOGFW("set window layout mode failed displayId: %{public}" PRIu64 ", ret: %{public}d", displayId, ret);
1193 }
1194 return ret;
1195 }
1196
GetAllDisplayIds() const1197 std::vector<DisplayId> WindowRoot::GetAllDisplayIds() const
1198 {
1199 std::vector<DisplayId> displayIds;
1200 for (auto& it : windowNodeContainerMap_) {
1201 if (!it.second) {
1202 return {};
1203 }
1204 std::vector<DisplayId>& displayIdVec = const_cast<WindowRoot*>(this)->displayIdMap_[it.first];
1205 for (auto displayId : displayIdVec) {
1206 displayIds.push_back(displayId);
1207 }
1208 }
1209 return displayIds;
1210 }
1211
GenAllWindowsLogInfo() const1212 std::string WindowRoot::GenAllWindowsLogInfo() const
1213 {
1214 std::ostringstream os;
1215 WindowNodeOperationFunc func = [&os](sptr<WindowNode> node) {
1216 if (node == nullptr) {
1217 WLOGE("WindowNode is nullptr");
1218 return false;
1219 }
1220 os<<"window_name:"<<node->GetWindowName()<<",id:"<<node->GetWindowId()<<
1221 ",focusable:"<<node->GetWindowProperty()->GetFocusable()<<";";
1222 return false;
1223 };
1224
1225 for (auto& elem : windowNodeContainerMap_) {
1226 if (elem.second == nullptr) {
1227 continue;
1228 }
1229 std::vector<DisplayId>& displayIdVec = const_cast<WindowRoot*>(this)->displayIdMap_[elem.first];
1230 for (const auto& displayId : displayIdVec) {
1231 os << "Display " << displayId << ":";
1232 }
1233 elem.second->TraverseWindowTree(func, true);
1234 }
1235 return os.str();
1236 }
1237
FocusFaultDetection() const1238 void WindowRoot::FocusFaultDetection() const
1239 {
1240 if (!needCheckFocusWindow) {
1241 return;
1242 }
1243 bool needReport = true;
1244 uint32_t focusWinId = INVALID_WINDOW_ID;
1245 for (auto& elem : windowNodeContainerMap_) {
1246 if (elem.second == nullptr) {
1247 continue;
1248 }
1249 focusWinId = elem.second->GetFocusWindow();
1250 if (focusWinId != INVALID_WINDOW_ID) {
1251 needReport = false;
1252 sptr<WindowNode> windowNode = GetWindowNode(focusWinId);
1253 if (windowNode == nullptr || !windowNode->currentVisibility_) {
1254 needReport = true;
1255 WLOGFE("The focus windowNode is nullptr or is invisible, focusWinId: %{public}u", focusWinId);
1256 break;
1257 }
1258 }
1259 }
1260 if (needReport) {
1261 std::string windowLog(GenAllWindowsLogInfo());
1262 WLOGFE("The focus window is faulty, focusWinId:%{public}u, %{public}s", focusWinId, windowLog.c_str());
1263 int32_t ret = OHOS::HiviewDFX::HiSysEvent::Write(
1264 OHOS::HiviewDFX::HiSysEvent::Domain::WINDOW_MANAGER,
1265 "NO_FOCUS_WINDOW",
1266 OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
1267 "PID", getpid(),
1268 "UID", getuid(),
1269 "PACKAGE_NAME", "foundation",
1270 "PROCESS_NAME", "foundation",
1271 "MSG", windowLog);
1272 if (ret != 0) {
1273 WLOGFE("Write HiSysEvent error, ret:%{public}d", ret);
1274 }
1275 }
1276 }
1277
ProcessExpandDisplayCreate(DisplayId defaultDisplayId,sptr<DisplayInfo> displayInfo,std::map<DisplayId,Rect> & displayRectMap)1278 void WindowRoot::ProcessExpandDisplayCreate(DisplayId defaultDisplayId, sptr<DisplayInfo> displayInfo,
1279 std::map<DisplayId, Rect>& displayRectMap)
1280 {
1281 if (displayInfo == nullptr || !CheckDisplayInfo(displayInfo)) {
1282 WLOGFE("get display failed or get invalid display info");
1283 return;
1284 }
1285 DisplayId displayId = displayInfo->GetDisplayId();
1286 ScreenId displayGroupId = displayInfo->GetScreenGroupId();
1287 auto container = windowNodeContainerMap_[displayGroupId];
1288 if (container == nullptr) {
1289 WLOGFE("window node container is nullptr, displayId :%{public}" PRIu64 "", displayId);
1290 return;
1291 }
1292
1293 WLOGFD("[Display Create] before add new display, displayId: %{public}" PRIu64"", displayId);
1294 container->GetMultiDisplayController()->ProcessDisplayCreate(defaultDisplayId, displayInfo, displayRectMap);
1295 WLOGFD("[Display Create] Container exist, add new display, displayId: %{public}" PRIu64"", displayId);
1296 }
1297
GetAllDisplayInfos(const std::vector<DisplayId> & displayIdVec)1298 std::map<DisplayId, sptr<DisplayInfo>> WindowRoot::GetAllDisplayInfos(const std::vector<DisplayId>& displayIdVec)
1299 {
1300 std::map<DisplayId, sptr<DisplayInfo>> displayInfoMap;
1301 for (auto& displayId : displayIdVec) {
1302 const sptr<DisplayInfo> displayInfo = DisplayManagerServiceInner::GetInstance().GetDisplayById(displayId);
1303 displayInfoMap.insert(std::make_pair(displayId, displayInfo));
1304 WLOGFD("Get latest displayInfo, displayId: %{public}" PRIu64"", displayId);
1305 }
1306 return displayInfoMap;
1307 }
1308
GetAllDisplayRectsByDMS(sptr<DisplayInfo> displayInfo)1309 std::map<DisplayId, Rect> WindowRoot::GetAllDisplayRectsByDMS(sptr<DisplayInfo> displayInfo)
1310 {
1311 std::map<DisplayId, Rect> displayRectMap;
1312
1313 if (displayInfo == nullptr) {
1314 return displayRectMap;
1315 }
1316
1317 for (auto& displayId : displayIdMap_[displayInfo->GetScreenGroupId()]) {
1318 auto info = DisplayManagerServiceInner::GetInstance().GetDisplayById(displayId);
1319 Rect displayRect = { info->GetOffsetX(), info->GetOffsetY(), info->GetWidth(), info->GetHeight() };
1320 displayRectMap.insert(std::make_pair(displayId, displayRect));
1321
1322 WLOGFD("displayId: %{public}" PRIu64", displayRect: [ %{public}d, %{public}d, %{public}d, %{public}d]",
1323 displayId, displayRect.posX_, displayRect.posY_, displayRect.width_, displayRect.height_);
1324 }
1325 return displayRectMap;
1326 }
1327
GetAllDisplayRectsByDisplayInfo(const std::map<DisplayId,sptr<DisplayInfo>> & displayInfoMap)1328 std::map<DisplayId, Rect> WindowRoot::GetAllDisplayRectsByDisplayInfo(
1329 const std::map<DisplayId, sptr<DisplayInfo>>& displayInfoMap)
1330 {
1331 std::map<DisplayId, Rect> displayRectMap;
1332
1333 for (const auto& iter : displayInfoMap) {
1334 auto id = iter.first;
1335 auto info = iter.second;
1336 Rect displayRect = { info->GetOffsetX(), info->GetOffsetY(), info->GetWidth(), info->GetHeight() };
1337 displayRectMap.insert(std::make_pair(id, displayRect));
1338
1339 WLOGFD("displayId: %{public}" PRIu64", displayRect: [ %{public}d, %{public}d, %{public}d, %{public}d]",
1340 id, displayRect.posX_, displayRect.posY_, displayRect.width_, displayRect.height_);
1341 }
1342 return displayRectMap;
1343 }
1344
ProcessDisplayCreate(DisplayId defaultDisplayId,sptr<DisplayInfo> displayInfo,const std::map<DisplayId,sptr<DisplayInfo>> & displayInfoMap)1345 void WindowRoot::ProcessDisplayCreate(DisplayId defaultDisplayId, sptr<DisplayInfo> displayInfo,
1346 const std::map<DisplayId, sptr<DisplayInfo>>& displayInfoMap)
1347 {
1348 DisplayId displayId = (displayInfo == nullptr) ? DISPLAY_ID_INVALID : displayInfo->GetDisplayId();
1349 ScreenId displayGroupId = (displayInfo == nullptr) ? SCREEN_ID_INVALID : displayInfo->GetScreenGroupId();
1350 auto iter = windowNodeContainerMap_.find(displayGroupId);
1351 if (iter == windowNodeContainerMap_.end()) {
1352 CreateWindowNodeContainer(displayInfo);
1353 WLOGFD("[Display Create] Create new container for display, displayId: %{public}" PRIu64"", displayId);
1354 } else {
1355 auto& displayIdVec = displayIdMap_[displayGroupId];
1356 if (std::find(displayIdVec.begin(), displayIdVec.end(), displayId) != displayIdVec.end()) {
1357 WLOGFD("[Display Create] Current display is already exist, displayId: %{public}" PRIu64"", displayId);
1358 return;
1359 }
1360 // add displayId in displayId vector
1361 displayIdMap_[displayGroupId].push_back(displayId);
1362 auto displayRectMap = GetAllDisplayRectsByDisplayInfo(displayInfoMap);
1363 ProcessExpandDisplayCreate(defaultDisplayId, displayInfo, displayRectMap);
1364 }
1365 }
1366
MoveNotShowingWindowToDefaultDisplay(DisplayId defaultDisplayId,DisplayId displayId)1367 void WindowRoot::MoveNotShowingWindowToDefaultDisplay(DisplayId defaultDisplayId, DisplayId displayId)
1368 {
1369 for (auto& elem : windowNodeMap_) {
1370 auto& windowNode = elem.second;
1371 if (windowNode->GetDisplayId() == displayId && !windowNode->currentVisibility_) {
1372 std::vector<DisplayId> newShowingDisplays = { defaultDisplayId };
1373 windowNode->SetShowingDisplays(newShowingDisplays);
1374 windowNode->isShowingOnMultiDisplays_ = false;
1375 if (windowNode->GetWindowToken()) {
1376 windowNode->GetWindowToken()->UpdateDisplayId(windowNode->GetDisplayId(), defaultDisplayId);
1377 }
1378 windowNode->SetDisplayId(defaultDisplayId);
1379 }
1380 }
1381 }
1382
ProcessDisplayDestroy(DisplayId defaultDisplayId,sptr<DisplayInfo> displayInfo,const std::map<DisplayId,sptr<DisplayInfo>> & displayInfoMap)1383 void WindowRoot::ProcessDisplayDestroy(DisplayId defaultDisplayId, sptr<DisplayInfo> displayInfo,
1384 const std::map<DisplayId, sptr<DisplayInfo>>& displayInfoMap)
1385 {
1386 DisplayId displayId = (displayInfo == nullptr) ? DISPLAY_ID_INVALID : displayInfo->GetDisplayId();
1387 ScreenId displayGroupId = (displayInfo == nullptr) ? SCREEN_ID_INVALID : displayInfo->GetScreenGroupId();
1388 auto& displayIdVec = displayIdMap_[displayGroupId];
1389
1390 auto iter = windowNodeContainerMap_.find(displayGroupId);
1391 if (iter == windowNodeContainerMap_.end() ||
1392 std::find(displayIdVec.begin(), displayIdVec.end(), displayId) == displayIdVec.end() ||
1393 displayInfoMap.find(displayId) == displayInfoMap.end()) {
1394 WLOGFE("[Display Destroy] could not find display, destroy failed, displayId: %{public}" PRIu64"", displayId);
1395 return;
1396 }
1397
1398 // erase displayId in displayIdMap
1399 auto displayIter = std::remove(displayIdVec.begin(), displayIdVec.end(), displayId);
1400 displayIdVec.erase(displayIter, displayIdVec.end());
1401
1402 // container process display destroy
1403 auto container = iter->second;
1404 if (container == nullptr) {
1405 WLOGFE("window node container is nullptr, displayId :%{public}" PRIu64 "", displayId);
1406 return;
1407 }
1408 WLOGFD("[Display Destroy] displayId: %{public}" PRIu64"", displayId);
1409
1410 std::vector<uint32_t> needDestroyWindows;
1411 auto displayRectMap = GetAllDisplayRectsByDisplayInfo(displayInfoMap);
1412 // erase displayId in displayRectMap
1413 auto displayRectIter = displayRectMap.find(displayId);
1414 if (displayRectIter == displayRectMap.end()) {
1415 return;
1416 }
1417 displayRectMap.erase(displayRectIter);
1418 container->GetMultiDisplayController()->ProcessDisplayDestroy(
1419 defaultDisplayId, displayInfo, displayRectMap, needDestroyWindows);
1420 for (auto id : needDestroyWindows) {
1421 auto node = GetWindowNode(id);
1422 if (node != nullptr) {
1423 DestroyWindowInner(node);
1424 }
1425 }
1426 // move window which is not showing on destroyed display to default display
1427 MoveNotShowingWindowToDefaultDisplay(defaultDisplayId, displayId);
1428 WLOGFD("[Display Destroy] displayId: %{public}" PRIu64" ", displayId);
1429 }
1430
ProcessDisplayChange(DisplayId defaultDisplayId,sptr<DisplayInfo> displayInfo,const std::map<DisplayId,sptr<DisplayInfo>> & displayInfoMap,DisplayStateChangeType type)1431 void WindowRoot::ProcessDisplayChange(DisplayId defaultDisplayId, sptr<DisplayInfo> displayInfo,
1432 const std::map<DisplayId, sptr<DisplayInfo>>& displayInfoMap, DisplayStateChangeType type)
1433 {
1434 if (displayInfo == nullptr) {
1435 WLOGFE("get display failed");
1436 return;
1437 }
1438 DisplayId displayId = displayInfo->GetDisplayId();
1439 ScreenId displayGroupId = displayInfo->GetScreenGroupId();
1440 auto& displayIdVec = displayIdMap_[displayGroupId];
1441 auto iter = windowNodeContainerMap_.find(displayGroupId);
1442 if (iter == windowNodeContainerMap_.end() || std::find(displayIdVec.begin(),
1443 displayIdVec.end(), displayId) == displayIdVec.end()) {
1444 WLOGFE("[Display Change] could not find display, change failed, displayId: %{public}" PRIu64"", displayId);
1445 return;
1446 }
1447 // container process display change
1448 auto container = iter->second;
1449 if (container == nullptr) {
1450 WLOGFE("window node container is nullptr, displayId :%{public}" PRIu64 "", displayId);
1451 return;
1452 }
1453
1454 auto displayRectMap = GetAllDisplayRectsByDisplayInfo(displayInfoMap);
1455 container->GetMultiDisplayController()->ProcessDisplayChange(defaultDisplayId, displayInfo, displayRectMap, type);
1456 }
1457
GetVirtualPixelRatio(DisplayId displayId) const1458 float WindowRoot::GetVirtualPixelRatio(DisplayId displayId) const
1459 {
1460 auto container = const_cast<WindowRoot*>(this)->GetOrCreateWindowNodeContainer(displayId);
1461 if (container == nullptr) {
1462 WLOGFE("window container could not be found");
1463 return 1.0; // Use DefaultVPR 1.0
1464 }
1465 return container->GetDisplayVirtualPixelRatio(displayId);
1466 }
1467
GetDisplayGroupRect(DisplayId displayId) const1468 Rect WindowRoot::GetDisplayGroupRect(DisplayId displayId) const
1469 {
1470 Rect fullDisplayRect;
1471 auto container = const_cast<WindowRoot*>(this)->GetOrCreateWindowNodeContainer(displayId);
1472 if (container == nullptr) {
1473 WLOGFE("window container could not be found");
1474 return fullDisplayRect;
1475 }
1476 return container->GetDisplayGroupRect();
1477 }
1478
HasPrivateWindow(DisplayId displayId)1479 bool WindowRoot::HasPrivateWindow(DisplayId displayId)
1480 {
1481 auto container = GetWindowNodeContainer(displayId);
1482 return container != nullptr ? container->HasPrivateWindow() : false;
1483 }
1484
SetMaxAppWindowNumber(uint32_t windowNum)1485 void WindowRoot::SetMaxAppWindowNumber(uint32_t windowNum)
1486 {
1487 maxAppWindowNumber_ = windowNum;
1488 }
1489
SetMaxUniRenderAppWindowNumber(uint32_t uniAppWindowNum)1490 void WindowRoot::SetMaxUniRenderAppWindowNumber(uint32_t uniAppWindowNum)
1491 {
1492 maxUniRenderAppWindowNumber_ = uniAppWindowNum;
1493 }
1494
GetMaxUniRenderAppWindowNumber() const1495 uint32_t WindowRoot::GetMaxUniRenderAppWindowNumber() const
1496 {
1497 return maxUniRenderAppWindowNumber_;
1498 }
1499
SetSplitRatios(const std::vector<float> & splitRatioNumbers)1500 void WindowRoot::SetSplitRatios(const std::vector<float>& splitRatioNumbers)
1501 {
1502 auto& splitRatios = splitRatioConfig_.splitRatios;
1503 splitRatios.clear();
1504 splitRatios = splitRatioNumbers;
1505 for (auto iter = splitRatios.begin(); iter != splitRatios.end();) {
1506 if (*iter > 0 && *iter < 1) { // valid ratio range (0, 1)
1507 iter++;
1508 } else {
1509 iter = splitRatios.erase(iter);
1510 }
1511 }
1512 std::sort(splitRatios.begin(), splitRatios.end());
1513 auto iter = std::unique(splitRatios.begin(), splitRatios.end());
1514 splitRatios.erase(iter, splitRatios.end()); // remove duplicate ratios
1515 }
1516
SetExitSplitRatios(const std::vector<float> & exitSplitRatios)1517 void WindowRoot::SetExitSplitRatios(const std::vector<float>& exitSplitRatios)
1518 {
1519 if (exitSplitRatios.size() != 2) {
1520 return;
1521 }
1522 if (exitSplitRatios[0] > 0 && exitSplitRatios[0] < DEFAULT_SPLIT_RATIO) {
1523 splitRatioConfig_.exitSplitStartRatio = exitSplitRatios[0];
1524 }
1525 if (exitSplitRatios[1] > DEFAULT_SPLIT_RATIO && exitSplitRatios[1] < 1) {
1526 splitRatioConfig_.exitSplitEndRatio = exitSplitRatios[1];
1527 }
1528 }
1529
GetModeChangeHotZones(DisplayId displayId,ModeChangeHotZones & hotZones,const ModeChangeHotZonesConfig & config)1530 WMError WindowRoot::GetModeChangeHotZones(DisplayId displayId,
1531 ModeChangeHotZones& hotZones, const ModeChangeHotZonesConfig& config)
1532 {
1533 auto container = GetOrCreateWindowNodeContainer(displayId);
1534 if (container == nullptr) {
1535 WLOGFE("GetModeChangeHotZones failed, window container could not be found");
1536 return WMError::WM_ERROR_NULLPTR;
1537 }
1538 container->GetModeChangeHotZones(displayId, hotZones, config);
1539 return WMError::WM_OK;
1540 }
1541
RemoveSingleUserWindowNodes(int accountId)1542 void WindowRoot::RemoveSingleUserWindowNodes(int accountId)
1543 {
1544 std::vector<DisplayId> displayIds = GetAllDisplayIds();
1545 for (auto id : displayIds) {
1546 sptr<WindowNodeContainer> container = GetOrCreateWindowNodeContainer(id);
1547 if (container == nullptr) {
1548 WLOGFD("get container failed %{public}" PRIu64"", id);
1549 continue;
1550 }
1551 container->RemoveSingleUserWindowNodes(accountId);
1552 }
1553 }
1554
UpdateRsTree(uint32_t windowId,bool isAdd)1555 WMError WindowRoot::UpdateRsTree(uint32_t windowId, bool isAdd)
1556 {
1557 sptr<WindowNode> node = GetWindowNode(windowId);
1558 if (node == nullptr) {
1559 WLOGFE("could not find window");
1560 return WMError::WM_ERROR_NULLPTR;
1561 }
1562 auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId());
1563 if (container == nullptr) {
1564 WLOGFE("window container could not be found");
1565 return WMError::WM_ERROR_NULLPTR;
1566 }
1567 for (auto& displayId : node->GetShowingDisplays()) {
1568 if (isAdd) {
1569 container->AddNodeOnRSTree(node, displayId, displayId, WindowUpdateType::WINDOW_UPDATE_ACTIVE);
1570 } else {
1571 container->RemoveNodeFromRSTree(node, displayId, displayId, WindowUpdateType::WINDOW_UPDATE_ACTIVE);
1572 }
1573 }
1574 RSTransaction::FlushImplicitTransaction();
1575 return WMError::WM_OK;
1576 }
1577
FindDialogCallerNode(WindowType type,sptr<IRemoteObject> token)1578 sptr<WindowNode> WindowRoot::FindDialogCallerNode(WindowType type, sptr<IRemoteObject> token)
1579 {
1580 if (type != WindowType::WINDOW_TYPE_DIALOG) {
1581 return nullptr;
1582 }
1583
1584 auto iter = std::find_if(windowNodeMap_.begin(), windowNodeMap_.end(),
1585 [token](const std::map<uint32_t, sptr<WindowNode>>::value_type& pair) {
1586 if (WindowHelper::IsMainWindow(pair.second->GetWindowType())) {
1587 return pair.second->abilityToken_ == token;
1588 }
1589 return false;
1590 });
1591 if (iter == windowNodeMap_.end()) {
1592 WLOGFD("cannot find windowNode");
1593 return nullptr;
1594 }
1595 return iter->second;
1596 }
1597
CheckMultiDialogWindows(WindowType type,sptr<IRemoteObject> token)1598 bool WindowRoot::CheckMultiDialogWindows(WindowType type, sptr<IRemoteObject> token)
1599 {
1600 if (type != WindowType::WINDOW_TYPE_DIALOG) {
1601 return false;
1602 }
1603
1604 sptr<WindowNode> newCaller, oriCaller;
1605
1606 newCaller = FindDialogCallerNode(type, token);
1607 if (newCaller == nullptr) {
1608 return false;
1609 }
1610
1611 for (auto& iter : windowNodeMap_) {
1612 if (iter.second->GetWindowType() == WindowType::WINDOW_TYPE_DIALOG) {
1613 oriCaller = FindDialogCallerNode(iter.second->GetWindowType(), iter.second->dialogTargetToken_);
1614 if (oriCaller == newCaller) {
1615 return true;
1616 }
1617 }
1618 }
1619
1620 return false;
1621 }
1622
OnRenderModeChanged(bool isUniRender)1623 void WindowRoot::OnRenderModeChanged(bool isUniRender)
1624 {
1625 WLOGFD("SwitchRender: render mode of RS has changed from %{public}u to %{public}s",
1626 static_cast<uint32_t>(renderMode_), std::to_string(isUniRender).c_str());
1627 if (isUniRender) {
1628 switch (renderMode_) {
1629 case RenderMode::SEPARATED:
1630 case RenderMode::UNIFYING:
1631 renderMode_ = RenderMode::UNIFIED;
1632 break;
1633 case RenderMode::SEPARATING:
1634 RSInterfaces::GetInstance().UpdateRenderMode(false);
1635 break;
1636 default:
1637 WLOGFE("SwitchRender: impossible code");
1638 break;
1639 }
1640 } else {
1641 switch (renderMode_) {
1642 case RenderMode::UNIFIED:
1643 case RenderMode::SEPARATING:
1644 renderMode_ = RenderMode::SEPARATED;
1645 break;
1646 case RenderMode::UNIFYING:
1647 RSInterfaces::GetInstance().UpdateRenderMode(true);
1648 break;
1649 default:
1650 WLOGFE("SwitchRender: impossible code");
1651 break;
1652 }
1653 }
1654 }
1655
SwitchRenderModeIfNeeded()1656 void WindowRoot::SwitchRenderModeIfNeeded()
1657 {
1658 if (displayIdMap_.empty()) {
1659 WLOGFE("WindowRoot::SwitchRenderModeIfNeeded: displayIdMap_ is empty");
1660 return;
1661 }
1662 if (displayIdMap_.size() != 1) {
1663 WLOGFE("WindowRoot::SwitchRenderModeIfNeeded: invalid screenGroup number");
1664 return;
1665 }
1666 uint32_t displayNum = displayIdMap_.begin()->second.size();
1667 if (displayNum > 1) {
1668 // switch to sperate render mode
1669 ChangeRSRenderModeIfNeeded(false);
1670 return;
1671 }
1672
1673 bool exceed = IsAppWindowExceed();
1674 if (exceed) {
1675 // switch to sperate render mode
1676 ChangeRSRenderModeIfNeeded(false);
1677 } else {
1678 // switch to unified render mode
1679 ChangeRSRenderModeIfNeeded(true);
1680 }
1681 }
1682
ChangeRSRenderModeIfNeeded(bool isToUnified)1683 void WindowRoot::ChangeRSRenderModeIfNeeded(bool isToUnified)
1684 {
1685 switch (renderMode_) {
1686 case RenderMode::SEPARATED:
1687 if (isToUnified) {
1688 WLOGFD("SwitchRender: notify RS from separated to be unifying");
1689 renderMode_ = RenderMode::UNIFYING;
1690 RSInterfaces::GetInstance().UpdateRenderMode(true);
1691 }
1692 break;
1693 case RenderMode::UNIFIED:
1694 if (!isToUnified) {
1695 WLOGFD("SwitchRender: notify RS from unified to be separating");
1696 renderMode_ = RenderMode::SEPARATING;
1697 RSInterfaces::GetInstance().UpdateRenderMode(false);
1698 }
1699 break;
1700 case RenderMode::SEPARATING:
1701 if (isToUnified) {
1702 WLOGFD("SwitchRender: notify RS from separating to be unifying");
1703 renderMode_ = RenderMode::UNIFYING;
1704 }
1705 break;
1706 case RenderMode::UNIFYING:
1707 if (!isToUnified) {
1708 WLOGFD("SwitchRender: notify RS from unifying to be separating");
1709 renderMode_ = RenderMode::SEPARATING;
1710 }
1711 break;
1712 default:
1713 WLOGE("SwitchRender: impossible code");
1714 break;
1715 }
1716 }
1717
IsAppWindowExceed() const1718 bool WindowRoot::IsAppWindowExceed() const
1719 {
1720 uint32_t appWindowNum = 0;
1721 for (const auto& it : windowNodeMap_) {
1722 WindowType winType = it.second->GetWindowType();
1723 WindowMode winMode = it.second->GetWindowMode();
1724 if (winMode == WindowMode::WINDOW_MODE_SPLIT_PRIMARY || winMode == WindowMode::WINDOW_MODE_SPLIT_SECONDARY) {
1725 return false;
1726 }
1727 if (winType >= WindowType::APP_WINDOW_BASE && winType < WindowType::APP_WINDOW_END &&
1728 it.second->currentVisibility_) {
1729 appWindowNum++;
1730 }
1731 }
1732 WLOGFD("SwitchRender: the number of app window is %{public}u", maxUniRenderAppWindowNumber_);
1733 return (appWindowNum > maxUniRenderAppWindowNumber_);
1734 }
1735
GetWindowNodeByAbilityToken(const sptr<IRemoteObject> & abilityToken)1736 sptr<WindowNode> WindowRoot::GetWindowNodeByAbilityToken(const sptr<IRemoteObject>& abilityToken)
1737 {
1738 for (const auto& iter : windowNodeMap_) {
1739 if (iter.second != nullptr && iter.second->abilityToken_ == abilityToken) {
1740 return iter.second;
1741 }
1742 }
1743 WLOGFE("could not find required abilityToken!");
1744 return nullptr;
1745 }
1746
TakeWindowPairSnapshot(DisplayId displayId)1747 bool WindowRoot::TakeWindowPairSnapshot(DisplayId displayId)
1748 {
1749 auto container = GetWindowNodeContainer(displayId);
1750 return container == nullptr ? false : container->TakeWindowPairSnapshot(displayId);
1751 }
1752
ClearWindowPairSnapshot(DisplayId displayId)1753 void WindowRoot::ClearWindowPairSnapshot(DisplayId displayId)
1754 {
1755 auto container = GetWindowNodeContainer(displayId);
1756 if (container == nullptr) {
1757 WLOGFE("clear window pair snapshot failed, because container in null");
1758 return;
1759 }
1760 return container->ClearWindowPairSnapshot(displayId);
1761 }
1762 } // namespace Rosen
1763 } // namespace OHOS
1764