• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
836     std::vector<uint32_t> windowIds;
837     WMError res = container->DestroyWindowNode(node, windowIds);
838     if (res != WMError::WM_OK) {
839         WLOGFE("RemoveWindowNode failed");
840     }
841     SwitchRenderModeIfNeeded();
842     return DestroyWindowInner(node);
843 }
844 
DestroyWindowWithChild(sptr<WindowNode> & node,const sptr<WindowNodeContainer> & container)845 WMError WindowRoot::DestroyWindowWithChild(sptr<WindowNode>& node, const sptr<WindowNodeContainer>& container)
846 {
847     auto token = node->abilityToken_;
848     std::vector<uint32_t> windowIds;
849     WMError res = container->DestroyWindowNode(node, windowIds);
850     for (auto id : windowIds) {
851         node = GetWindowNode(id);
852         if (!node) {
853             continue;
854         }
855         HandleKeepScreenOn(id, false);
856         DestroyWindowInner(node);
857         if ((node->GetWindowToken() != nullptr) && (node->abilityToken_ != token) &&
858             (node->GetWindowType() == WindowType::WINDOW_TYPE_DIALOG)) {
859             node->GetWindowToken()->NotifyDestroy();
860         }
861     }
862     SwitchRenderModeIfNeeded();
863     return res;
864 }
865 
DestroyWindow(uint32_t windowId,bool onlySelf)866 WMError WindowRoot::DestroyWindow(uint32_t windowId, bool onlySelf)
867 {
868     auto node = GetWindowNode(windowId);
869     if (node == nullptr) {
870         WLOGFE("destroy window failed, because window node is not exist.");
871         return WMError::WM_ERROR_NULLPTR;
872     }
873     WLOGFD("destroy window %{public}u, onlySelf:%{public}u.", windowId, onlySelf);
874     auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId());
875     if (!container) {
876         WLOGFW("destroy window failed, window container could not be found");
877         return DestroyWindowInner(node);
878     }
879 
880     UpdateFocusWindowWithWindowRemoved(node, container);
881     UpdateActiveWindowWithWindowRemoved(node, container);
882     UpdateBrightnessWithWindowRemoved(windowId, container);
883     HandleKeepScreenOn(windowId, false);
884     if (onlySelf) {
885         return DestroyWindowSelf(node, container);
886     } else {
887         return DestroyWindowWithChild(node, container);
888     }
889 }
890 
DestroyWindowInner(sptr<WindowNode> & node)891 WMError WindowRoot::DestroyWindowInner(sptr<WindowNode>& node)
892 {
893     if (node == nullptr) {
894         WLOGFE("window has been destroyed");
895         return WMError::WM_ERROR_DESTROYED_OBJECT;
896     }
897 
898     if (node->isVisible_) {
899         std::vector<sptr<WindowVisibilityInfo>> windowVisibilityInfos;
900         node->isVisible_ = false;
901         windowVisibilityInfos.emplace_back(new WindowVisibilityInfo(node->GetWindowId(), node->GetCallingPid(),
902             node->GetCallingUid(), false, node->GetWindowType()));
903         WLOGFD("NotifyWindowVisibilityChange: covered status changed window:%{public}u, isVisible:%{public}d",
904             node->GetWindowId(), node->isVisible_);
905         WindowManagerAgentController::GetInstance().UpdateWindowVisibilityInfo(windowVisibilityInfos);
906     }
907 
908     auto cmpFunc = [node](const std::map<uint64_t, sptr<WindowNode>>::value_type& pair) {
909         if (pair.second == nullptr) {
910             return false;
911         }
912         if (pair.second->GetWindowId() == node->GetWindowId()) {
913             return true;
914         }
915         return false;
916     };
917     auto iter = std::find_if(surfaceIdWindowNodeMap_.begin(), surfaceIdWindowNodeMap_.end(), cmpFunc);
918     if (iter != surfaceIdWindowNodeMap_.end()) {
919         surfaceIdWindowNodeMap_.erase(iter);
920     }
921 
922     sptr<IWindow> window = node->GetWindowToken();
923     if ((window != nullptr) && (window->AsObject() != nullptr)) {
924         if (windowIdMap_.count(window->AsObject()) == 0) {
925             WLOGFD("window remote object has been destroyed");
926             return WMError::WM_ERROR_DESTROYED_OBJECT;
927         }
928 
929         if (window->AsObject() != nullptr) {
930             window->AsObject()->RemoveDeathRecipient(windowDeath_);
931         }
932         windowIdMap_.erase(window->AsObject());
933     }
934     windowNodeMap_.erase(node->GetWindowId());
935     WLOGFD("destroy window node use_count:%{public}d", node->GetSptrRefCount());
936     return WMError::WM_OK;
937 }
938 
UpdateFocusWindowWithWindowRemoved(const sptr<WindowNode> & node,const sptr<WindowNodeContainer> & container) const939 void WindowRoot::UpdateFocusWindowWithWindowRemoved(const sptr<WindowNode>& node,
940     const sptr<WindowNodeContainer>& container) const
941 {
942     if (node == nullptr || container == nullptr) {
943         WLOGFE("window is invalid");
944         return;
945     }
946     if (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) {
947         WLOGFD("window is divider, do not get next focus window.");
948         return;
949     }
950     uint32_t windowId = node->GetWindowId();
951     uint32_t focusedWindowId = container->GetFocusWindow();
952     WLOGFD("current window: %{public}u, focus window: %{public}u", windowId, focusedWindowId);
953     if (WindowHelper::IsMainWindow(node->GetWindowType())) {
954         if (windowId != focusedWindowId) {
955             auto iter = std::find_if(node->children_.begin(), node->children_.end(),
956                                      [focusedWindowId](sptr<WindowNode> node) {
957                                          return node->GetWindowId() == focusedWindowId;
958                                      });
959             if (iter == node->children_.end()) {
960                 return;
961             }
962         }
963         if (!node->children_.empty()) {
964             auto firstChild = node->children_.front();
965             if (firstChild->priority_ < 0) {
966                 windowId = firstChild->GetWindowId();
967             }
968         }
969     } else {
970         if (windowId != focusedWindowId) {
971             return;
972         }
973     }
974     auto nextFocusableWindow = container->GetNextFocusableWindow(windowId);
975     if (nextFocusableWindow != nullptr) {
976         WLOGFD("adjust focus window, next focus window id: %{public}u", nextFocusableWindow->GetWindowId());
977         container->SetFocusWindow(nextFocusableWindow->GetWindowId());
978     }
979 }
980 
UpdateActiveWindowWithWindowRemoved(const sptr<WindowNode> & node,const sptr<WindowNodeContainer> & container) const981 void WindowRoot::UpdateActiveWindowWithWindowRemoved(const sptr<WindowNode>& node,
982     const sptr<WindowNodeContainer>& container) const
983 {
984     if (node == nullptr || container == nullptr) {
985         WLOGFE("window is invalid");
986         return;
987     }
988     uint32_t windowId = node->GetWindowId();
989     uint32_t activeWindowId = container->GetActiveWindow();
990     WLOGFD("current window: %{public}u, active window: %{public}u", windowId, activeWindowId);
991     if (WindowHelper::IsMainWindow(node->GetWindowType())) {
992         if (windowId != activeWindowId) {
993             auto iter = std::find_if(node->children_.begin(), node->children_.end(),
994                                      [activeWindowId](sptr<WindowNode> node) {
995                                          return node->GetWindowId() == activeWindowId;
996                                      });
997             if (iter == node->children_.end()) {
998                 return;
999             }
1000         }
1001         if (!node->children_.empty()) {
1002             auto firstChild = node->children_.front();
1003             if (firstChild->priority_ < 0) {
1004                 windowId = firstChild->GetWindowId();
1005             }
1006         }
1007     } else {
1008         if (windowId != activeWindowId) {
1009             return;
1010         }
1011     }
1012     auto nextActiveWindow = container->GetNextActiveWindow(windowId);
1013     if (nextActiveWindow != nullptr) {
1014         WLOGFD("adjust active window, next active window id: %{public}u", nextActiveWindow->GetWindowId());
1015         container->SetActiveWindow(nextActiveWindow->GetWindowId(), true);
1016     }
1017 }
1018 
UpdateBrightnessWithWindowRemoved(uint32_t windowId,const sptr<WindowNodeContainer> & container) const1019 void WindowRoot::UpdateBrightnessWithWindowRemoved(uint32_t windowId, const sptr<WindowNodeContainer>& container) const
1020 {
1021     if (container == nullptr) {
1022         WLOGFE("window container could not be found");
1023         return;
1024     }
1025     if (windowId == container->GetBrightnessWindow()) {
1026         WLOGFD("adjust brightness window with active window: %{public}u", container->GetActiveWindow());
1027         container->UpdateBrightness(container->GetActiveWindow(), true);
1028     }
1029 }
1030 
IsVerticalDisplay(sptr<WindowNode> & node) const1031 bool WindowRoot::IsVerticalDisplay(sptr<WindowNode>& node) const
1032 {
1033     auto container = const_cast<WindowRoot*>(this)->GetOrCreateWindowNodeContainer(node->GetDisplayId());
1034     if (container == nullptr) {
1035         WLOGFE("get display direction failed, window container could not be found");
1036         return false;
1037     }
1038     return container->IsVerticalDisplay(node->GetDisplayId());
1039 }
1040 
RequestFocus(uint32_t windowId)1041 WMError WindowRoot::RequestFocus(uint32_t windowId)
1042 {
1043     auto node = GetWindowNode(windowId);
1044     if (node == nullptr) {
1045         WLOGFE("could not find window");
1046         return WMError::WM_ERROR_NULLPTR;
1047     }
1048     if (!node->currentVisibility_) {
1049         WLOGFE("could not request focus before it does not be shown");
1050         return WMError::WM_ERROR_INVALID_OPERATION;
1051     }
1052     auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId());
1053     if (container == nullptr) {
1054         WLOGFE("window container could not be found");
1055         return WMError::WM_ERROR_NULLPTR;
1056     }
1057     if (node->GetWindowProperty()->GetFocusable()) {
1058         return container->SetFocusWindow(windowId);
1059     }
1060     return WMError::WM_ERROR_INVALID_OPERATION;
1061 }
1062 
RequestActiveWindow(uint32_t windowId)1063 WMError WindowRoot::RequestActiveWindow(uint32_t windowId)
1064 {
1065     auto node = GetWindowNode(windowId);
1066     if (node == nullptr) {
1067         WLOGFE("could not find window");
1068         return WMError::WM_ERROR_NULLPTR;
1069     }
1070     if (WindowHelper::IsSystemBarWindow(node->GetWindowType())) {
1071         WLOGFE("window could not be active window");
1072         return WMError::WM_ERROR_INVALID_TYPE;
1073     }
1074     auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId());
1075     if (container == nullptr) {
1076         WLOGFE("window container could not be found");
1077         return WMError::WM_ERROR_NULLPTR;
1078     }
1079     auto res = container->SetActiveWindow(windowId, false);
1080     WLOGFD("windowId:%{public}u, name:%{public}s, orientation:%{public}u, type:%{public}u, isMainWindow:%{public}d",
1081         windowId, node->GetWindowName().c_str(), static_cast<uint32_t>(node->GetRequestedOrientation()),
1082         node->GetWindowType(), WindowHelper::IsMainWindow(node->GetWindowType()));
1083     if (res == WMError::WM_OK &&
1084         WindowHelper::IsRotatableWindow(node->GetWindowType(), node->GetWindowMode())) {
1085         DisplayManagerServiceInner::GetInstance().
1086             SetOrientationFromWindow(node->GetDisplayId(), node->GetRequestedOrientation());
1087     }
1088     return res;
1089 }
1090 
ProcessWindowStateChange(WindowState state,WindowStateChangeReason reason)1091 void WindowRoot::ProcessWindowStateChange(WindowState state, WindowStateChangeReason reason)
1092 {
1093     for (auto& elem : windowNodeContainerMap_) {
1094         if (elem.second == nullptr) {
1095             continue;
1096         }
1097         elem.second->ProcessWindowStateChange(state, reason);
1098     }
1099 }
1100 
NotifySystemBarTints()1101 void WindowRoot::NotifySystemBarTints()
1102 {
1103     WLOGFD("notify current system bar tints");
1104     for (auto& it : windowNodeContainerMap_) {
1105         if (it.second != nullptr) {
1106             it.second->NotifySystemBarTints(displayIdMap_[it.first]);
1107         }
1108     }
1109 }
1110 
RaiseZOrderForAppWindow(sptr<WindowNode> & node)1111 WMError WindowRoot::RaiseZOrderForAppWindow(sptr<WindowNode>& node)
1112 {
1113     if (node == nullptr) {
1114         WLOGFW("add window failed, node is nullptr");
1115         return WMError::WM_ERROR_NULLPTR;
1116     }
1117     if (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) {
1118         auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId());
1119         if (container == nullptr) {
1120             WLOGFW("window container could not be found");
1121             return WMError::WM_ERROR_NULLPTR;
1122         }
1123         container->RaiseSplitRelatedWindowToTop(node);
1124         return WMError::WM_OK;
1125     }
1126     if (node->GetWindowType() == WindowType::WINDOW_TYPE_DIALOG) {
1127         auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId());
1128         if (container == nullptr) {
1129             WLOGFW("window container could not be found");
1130             return WMError::WM_ERROR_NULLPTR;
1131         }
1132         sptr<WindowNode> parentNode = FindDialogCallerNode(node->GetWindowType(), node->dialogTargetToken_);
1133         if (parentNode != nullptr) {
1134             container->RaiseZOrderForAppWindow(node, parentNode);
1135         }
1136         return WMError::WM_OK;
1137     }
1138 
1139     if (!WindowHelper::IsAppWindow(node->GetWindowType())) {
1140         WLOGFW("window is not app window");
1141         return WMError::WM_ERROR_INVALID_TYPE;
1142     }
1143     auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId());
1144     if (container == nullptr) {
1145         WLOGFW("add window failed, window container could not be found");
1146         return WMError::WM_ERROR_NULLPTR;
1147     }
1148 
1149     auto parentNode = GetWindowNode(node->GetParentId());
1150     return container->RaiseZOrderForAppWindow(node, parentNode);
1151 }
1152 
GetWindowIdByObject(const sptr<IRemoteObject> & remoteObject)1153 uint32_t WindowRoot::GetWindowIdByObject(const sptr<IRemoteObject>& remoteObject)
1154 {
1155     auto iter = windowIdMap_.find(remoteObject);
1156     return iter == std::end(windowIdMap_) ? INVALID_WINDOW_ID : iter->second;
1157 }
1158 
OnRemoteDied(const sptr<IRemoteObject> & remoteObject)1159 void WindowRoot::OnRemoteDied(const sptr<IRemoteObject>& remoteObject)
1160 {
1161     callback_(Event::REMOTE_DIED, remoteObject);
1162 }
1163 
GetTopWindowId(uint32_t mainWinId,uint32_t & topWinId)1164 WMError WindowRoot::GetTopWindowId(uint32_t mainWinId, uint32_t& topWinId)
1165 {
1166     if (windowNodeMap_.find(mainWinId) == windowNodeMap_.end()) {
1167         return WMError::WM_ERROR_INVALID_WINDOW;
1168     }
1169     auto node = windowNodeMap_[mainWinId];
1170     if (!node->currentVisibility_) {
1171         return WMError::WM_ERROR_INVALID_WINDOW;
1172     }
1173     if (!node->children_.empty()) {
1174         auto iter = node->children_.rbegin();
1175         if (WindowHelper::IsSubWindow((*iter)->GetWindowType()) ||
1176             WindowHelper::IsSystemSubWindow((*iter)->GetWindowType())) {
1177             topWinId = (*iter)->GetWindowId();
1178             return WMError::WM_OK;
1179         }
1180     }
1181     topWinId = mainWinId;
1182     return WMError::WM_OK;
1183 }
1184 
SetWindowLayoutMode(DisplayId displayId,WindowLayoutMode mode)1185 WMError WindowRoot::SetWindowLayoutMode(DisplayId displayId, WindowLayoutMode mode)
1186 {
1187     auto container = GetOrCreateWindowNodeContainer(displayId);
1188     if (container == nullptr) {
1189         WLOGFE("window container could not be found");
1190         return WMError::WM_ERROR_NULLPTR;
1191     }
1192     WMError ret = container->SwitchLayoutPolicy(mode, displayId, true);
1193     if (ret != WMError::WM_OK) {
1194         WLOGFW("set window layout mode failed displayId: %{public}" PRIu64 ", ret: %{public}d", displayId, ret);
1195     }
1196     return ret;
1197 }
1198 
GetAllDisplayIds() const1199 std::vector<DisplayId> WindowRoot::GetAllDisplayIds() const
1200 {
1201     std::vector<DisplayId> displayIds;
1202     for (auto& it : windowNodeContainerMap_) {
1203         if (!it.second) {
1204             return {};
1205         }
1206         std::vector<DisplayId>& displayIdVec = const_cast<WindowRoot*>(this)->displayIdMap_[it.first];
1207         for (auto displayId : displayIdVec) {
1208             displayIds.push_back(displayId);
1209         }
1210     }
1211     return displayIds;
1212 }
1213 
GenAllWindowsLogInfo() const1214 std::string WindowRoot::GenAllWindowsLogInfo() const
1215 {
1216     std::ostringstream os;
1217     WindowNodeOperationFunc func = [&os](sptr<WindowNode> node) {
1218         if (node == nullptr) {
1219             WLOGE("WindowNode is nullptr");
1220             return false;
1221         }
1222         os<<"window_name:"<<node->GetWindowName()<<",id:"<<node->GetWindowId()<<
1223            ",focusable:"<<node->GetWindowProperty()->GetFocusable()<<";";
1224         return false;
1225     };
1226 
1227     for (auto& elem : windowNodeContainerMap_) {
1228         if (elem.second == nullptr) {
1229             continue;
1230         }
1231         std::vector<DisplayId>& displayIdVec = const_cast<WindowRoot*>(this)->displayIdMap_[elem.first];
1232         for (const auto& displayId : displayIdVec) {
1233             os << "Display " << displayId << ":";
1234         }
1235         elem.second->TraverseWindowTree(func, true);
1236     }
1237     return os.str();
1238 }
1239 
FocusFaultDetection() const1240 void WindowRoot::FocusFaultDetection() const
1241 {
1242     if (!needCheckFocusWindow) {
1243         return;
1244     }
1245     bool needReport = true;
1246     uint32_t focusWinId = INVALID_WINDOW_ID;
1247     for (auto& elem : windowNodeContainerMap_) {
1248         if (elem.second == nullptr) {
1249             continue;
1250         }
1251         focusWinId = elem.second->GetFocusWindow();
1252         if (focusWinId != INVALID_WINDOW_ID) {
1253             needReport = false;
1254             sptr<WindowNode> windowNode = GetWindowNode(focusWinId);
1255             if (windowNode == nullptr || !windowNode->currentVisibility_) {
1256                 needReport = true;
1257                 WLOGFE("The focus windowNode is nullptr or is invisible, focusWinId: %{public}u", focusWinId);
1258                 break;
1259             }
1260         }
1261     }
1262     if (needReport) {
1263         std::string windowLog(GenAllWindowsLogInfo());
1264         WLOGFE("The focus window is faulty, focusWinId:%{public}u, %{public}s", focusWinId, windowLog.c_str());
1265         int32_t ret = OHOS::HiviewDFX::HiSysEvent::Write(
1266             OHOS::HiviewDFX::HiSysEvent::Domain::WINDOW_MANAGER,
1267             "NO_FOCUS_WINDOW",
1268             OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
1269             "PID", getpid(),
1270             "UID", getuid(),
1271             "PACKAGE_NAME", "foundation",
1272             "PROCESS_NAME", "foundation",
1273             "MSG", windowLog);
1274         if (ret != 0) {
1275             WLOGFE("Write HiSysEvent error, ret:%{public}d", ret);
1276         }
1277     }
1278 }
1279 
ProcessExpandDisplayCreate(DisplayId defaultDisplayId,sptr<DisplayInfo> displayInfo,std::map<DisplayId,Rect> & displayRectMap)1280 void WindowRoot::ProcessExpandDisplayCreate(DisplayId defaultDisplayId, sptr<DisplayInfo> displayInfo,
1281     std::map<DisplayId, Rect>& displayRectMap)
1282 {
1283     if (displayInfo == nullptr || !CheckDisplayInfo(displayInfo)) {
1284         WLOGFE("get display failed or get invalid display info");
1285         return;
1286     }
1287     DisplayId displayId = displayInfo->GetDisplayId();
1288     ScreenId displayGroupId = displayInfo->GetScreenGroupId();
1289     auto container = windowNodeContainerMap_[displayGroupId];
1290     if (container == nullptr) {
1291         WLOGFE("window node container is nullptr, displayId :%{public}" PRIu64 "", displayId);
1292         return;
1293     }
1294 
1295     WLOGFD("[Display Create] before add new display, displayId: %{public}" PRIu64"", displayId);
1296     container->GetMultiDisplayController()->ProcessDisplayCreate(defaultDisplayId, displayInfo, displayRectMap);
1297     WLOGFD("[Display Create] Container exist, add new display, displayId: %{public}" PRIu64"", displayId);
1298 }
1299 
GetAllDisplayInfos(const std::vector<DisplayId> & displayIdVec)1300 std::map<DisplayId, sptr<DisplayInfo>> WindowRoot::GetAllDisplayInfos(const std::vector<DisplayId>& displayIdVec)
1301 {
1302     std::map<DisplayId, sptr<DisplayInfo>> displayInfoMap;
1303     for (auto& displayId : displayIdVec) {
1304         const sptr<DisplayInfo> displayInfo = DisplayManagerServiceInner::GetInstance().GetDisplayById(displayId);
1305         displayInfoMap.insert(std::make_pair(displayId, displayInfo));
1306         WLOGFD("Get latest displayInfo, displayId: %{public}" PRIu64"", displayId);
1307     }
1308     return displayInfoMap;
1309 }
1310 
GetAllDisplayRectsByDMS(sptr<DisplayInfo> displayInfo)1311 std::map<DisplayId, Rect> WindowRoot::GetAllDisplayRectsByDMS(sptr<DisplayInfo> displayInfo)
1312 {
1313     std::map<DisplayId, Rect> displayRectMap;
1314 
1315     if (displayInfo == nullptr) {
1316         return displayRectMap;
1317     }
1318 
1319     for (auto& displayId : displayIdMap_[displayInfo->GetScreenGroupId()]) {
1320         auto info = DisplayManagerServiceInner::GetInstance().GetDisplayById(displayId);
1321         Rect displayRect = { info->GetOffsetX(), info->GetOffsetY(), info->GetWidth(), info->GetHeight() };
1322         displayRectMap.insert(std::make_pair(displayId, displayRect));
1323 
1324         WLOGFD("displayId: %{public}" PRIu64", displayRect: [ %{public}d, %{public}d, %{public}d, %{public}d]",
1325             displayId, displayRect.posX_, displayRect.posY_, displayRect.width_, displayRect.height_);
1326     }
1327     return displayRectMap;
1328 }
1329 
GetAllDisplayRectsByDisplayInfo(const std::map<DisplayId,sptr<DisplayInfo>> & displayInfoMap)1330 std::map<DisplayId, Rect> WindowRoot::GetAllDisplayRectsByDisplayInfo(
1331     const std::map<DisplayId, sptr<DisplayInfo>>& displayInfoMap)
1332 {
1333     std::map<DisplayId, Rect> displayRectMap;
1334 
1335     for (const auto& iter : displayInfoMap) {
1336         auto id = iter.first;
1337         auto info = iter.second;
1338         Rect displayRect = { info->GetOffsetX(), info->GetOffsetY(), info->GetWidth(), info->GetHeight() };
1339         displayRectMap.insert(std::make_pair(id, displayRect));
1340 
1341         WLOGFD("displayId: %{public}" PRIu64", displayRect: [ %{public}d, %{public}d, %{public}d, %{public}d]",
1342             id, displayRect.posX_, displayRect.posY_, displayRect.width_, displayRect.height_);
1343     }
1344     return displayRectMap;
1345 }
1346 
ProcessDisplayCreate(DisplayId defaultDisplayId,sptr<DisplayInfo> displayInfo,const std::map<DisplayId,sptr<DisplayInfo>> & displayInfoMap)1347 void WindowRoot::ProcessDisplayCreate(DisplayId defaultDisplayId, sptr<DisplayInfo> displayInfo,
1348     const std::map<DisplayId, sptr<DisplayInfo>>& displayInfoMap)
1349 {
1350     DisplayId displayId = (displayInfo == nullptr) ? DISPLAY_ID_INVALID : displayInfo->GetDisplayId();
1351     ScreenId displayGroupId = (displayInfo == nullptr) ? SCREEN_ID_INVALID : displayInfo->GetScreenGroupId();
1352     auto iter = windowNodeContainerMap_.find(displayGroupId);
1353     if (iter == windowNodeContainerMap_.end()) {
1354         CreateWindowNodeContainer(displayInfo);
1355         WLOGFD("[Display Create] Create new container for display, displayId: %{public}" PRIu64"", displayId);
1356     } else {
1357         auto& displayIdVec = displayIdMap_[displayGroupId];
1358         if (std::find(displayIdVec.begin(), displayIdVec.end(), displayId) != displayIdVec.end()) {
1359             WLOGFD("[Display Create] Current display is already exist, displayId: %{public}" PRIu64"", displayId);
1360             return;
1361         }
1362         // add displayId in displayId vector
1363         displayIdMap_[displayGroupId].push_back(displayId);
1364         auto displayRectMap = GetAllDisplayRectsByDisplayInfo(displayInfoMap);
1365         ProcessExpandDisplayCreate(defaultDisplayId, displayInfo, displayRectMap);
1366     }
1367 }
1368 
MoveNotShowingWindowToDefaultDisplay(DisplayId defaultDisplayId,DisplayId displayId)1369 void WindowRoot::MoveNotShowingWindowToDefaultDisplay(DisplayId defaultDisplayId, DisplayId displayId)
1370 {
1371     for (auto& elem : windowNodeMap_) {
1372         auto& windowNode = elem.second;
1373         if (windowNode->GetDisplayId() == displayId && !windowNode->currentVisibility_) {
1374             std::vector<DisplayId> newShowingDisplays = { defaultDisplayId };
1375             windowNode->SetShowingDisplays(newShowingDisplays);
1376             windowNode->isShowingOnMultiDisplays_ = false;
1377             if (windowNode->GetWindowToken()) {
1378                 windowNode->GetWindowToken()->UpdateDisplayId(windowNode->GetDisplayId(), defaultDisplayId);
1379             }
1380             windowNode->SetDisplayId(defaultDisplayId);
1381         }
1382     }
1383 }
1384 
ProcessDisplayDestroy(DisplayId defaultDisplayId,sptr<DisplayInfo> displayInfo,const std::map<DisplayId,sptr<DisplayInfo>> & displayInfoMap)1385 void WindowRoot::ProcessDisplayDestroy(DisplayId defaultDisplayId, sptr<DisplayInfo> displayInfo,
1386     const std::map<DisplayId, sptr<DisplayInfo>>& displayInfoMap)
1387 {
1388     DisplayId displayId = (displayInfo == nullptr) ? DISPLAY_ID_INVALID : displayInfo->GetDisplayId();
1389     ScreenId displayGroupId = (displayInfo == nullptr) ? SCREEN_ID_INVALID : displayInfo->GetScreenGroupId();
1390     auto& displayIdVec = displayIdMap_[displayGroupId];
1391 
1392     auto iter = windowNodeContainerMap_.find(displayGroupId);
1393     if (iter == windowNodeContainerMap_.end() ||
1394         std::find(displayIdVec.begin(), displayIdVec.end(), displayId) == displayIdVec.end() ||
1395         displayInfoMap.find(displayId) == displayInfoMap.end()) {
1396         WLOGFE("[Display Destroy] could not find display, destroy failed, displayId: %{public}" PRIu64"", displayId);
1397         return;
1398     }
1399 
1400     // erase displayId in displayIdMap
1401     auto displayIter = std::remove(displayIdVec.begin(), displayIdVec.end(), displayId);
1402     displayIdVec.erase(displayIter, displayIdVec.end());
1403 
1404     // container process display destroy
1405     auto container = iter->second;
1406     if (container == nullptr) {
1407         WLOGFE("window node container is nullptr, displayId :%{public}" PRIu64 "", displayId);
1408         return;
1409     }
1410     WLOGFD("[Display Destroy] displayId: %{public}" PRIu64"", displayId);
1411 
1412     std::vector<uint32_t> needDestroyWindows;
1413     auto displayRectMap = GetAllDisplayRectsByDisplayInfo(displayInfoMap);
1414     // erase displayId in displayRectMap
1415     auto displayRectIter = displayRectMap.find(displayId);
1416     if (displayRectIter == displayRectMap.end()) {
1417         return;
1418     }
1419     displayRectMap.erase(displayRectIter);
1420     container->GetMultiDisplayController()->ProcessDisplayDestroy(
1421         defaultDisplayId, displayInfo, displayRectMap, needDestroyWindows);
1422     for (auto id : needDestroyWindows) {
1423         auto node = GetWindowNode(id);
1424         if (node != nullptr) {
1425             DestroyWindowInner(node);
1426         }
1427     }
1428     // move window which is not showing on destroyed display to default display
1429     MoveNotShowingWindowToDefaultDisplay(defaultDisplayId, displayId);
1430     WLOGFD("[Display Destroy] displayId: %{public}" PRIu64" ", displayId);
1431 }
1432 
ProcessDisplayChange(DisplayId defaultDisplayId,sptr<DisplayInfo> displayInfo,const std::map<DisplayId,sptr<DisplayInfo>> & displayInfoMap,DisplayStateChangeType type)1433 void WindowRoot::ProcessDisplayChange(DisplayId defaultDisplayId, sptr<DisplayInfo> displayInfo,
1434     const std::map<DisplayId, sptr<DisplayInfo>>& displayInfoMap, DisplayStateChangeType type)
1435 {
1436     if (displayInfo == nullptr) {
1437         WLOGFE("get display failed");
1438         return;
1439     }
1440     DisplayId displayId = displayInfo->GetDisplayId();
1441     ScreenId displayGroupId = displayInfo->GetScreenGroupId();
1442     auto& displayIdVec = displayIdMap_[displayGroupId];
1443     auto iter = windowNodeContainerMap_.find(displayGroupId);
1444     if (iter == windowNodeContainerMap_.end() || std::find(displayIdVec.begin(),
1445         displayIdVec.end(), displayId) == displayIdVec.end()) {
1446         WLOGFE("[Display Change] could not find display, change failed, displayId: %{public}" PRIu64"", displayId);
1447         return;
1448     }
1449     // container process display change
1450     auto container = iter->second;
1451     if (container == nullptr) {
1452         WLOGFE("window node container is nullptr, displayId :%{public}" PRIu64 "", displayId);
1453         return;
1454     }
1455 
1456     auto displayRectMap = GetAllDisplayRectsByDisplayInfo(displayInfoMap);
1457     container->GetMultiDisplayController()->ProcessDisplayChange(defaultDisplayId, displayInfo, displayRectMap, type);
1458 }
1459 
GetVirtualPixelRatio(DisplayId displayId) const1460 float WindowRoot::GetVirtualPixelRatio(DisplayId displayId) const
1461 {
1462     auto container = const_cast<WindowRoot*>(this)->GetOrCreateWindowNodeContainer(displayId);
1463     if (container == nullptr) {
1464         WLOGFE("window container could not be found");
1465         return 1.0;  // Use DefaultVPR 1.0
1466     }
1467     return container->GetDisplayVirtualPixelRatio(displayId);
1468 }
1469 
GetDisplayGroupRect(DisplayId displayId) const1470 Rect WindowRoot::GetDisplayGroupRect(DisplayId displayId) const
1471 {
1472     Rect fullDisplayRect;
1473     auto container = const_cast<WindowRoot*>(this)->GetOrCreateWindowNodeContainer(displayId);
1474     if (container == nullptr) {
1475         WLOGFE("window container could not be found");
1476         return fullDisplayRect;
1477     }
1478     return container->GetDisplayGroupRect();
1479 }
1480 
HasPrivateWindow(DisplayId displayId)1481 bool WindowRoot::HasPrivateWindow(DisplayId displayId)
1482 {
1483     auto container = GetWindowNodeContainer(displayId);
1484     return container != nullptr ? container->HasPrivateWindow() : false;
1485 }
1486 
SetMaxAppWindowNumber(uint32_t windowNum)1487 void WindowRoot::SetMaxAppWindowNumber(uint32_t windowNum)
1488 {
1489     maxAppWindowNumber_ = windowNum;
1490 }
1491 
SetMaxUniRenderAppWindowNumber(uint32_t uniAppWindowNum)1492 void WindowRoot::SetMaxUniRenderAppWindowNumber(uint32_t uniAppWindowNum)
1493 {
1494     maxUniRenderAppWindowNumber_ = uniAppWindowNum;
1495 }
1496 
GetMaxUniRenderAppWindowNumber() const1497 uint32_t WindowRoot::GetMaxUniRenderAppWindowNumber() const
1498 {
1499     return maxUniRenderAppWindowNumber_;
1500 }
1501 
SetSplitRatios(const std::vector<float> & splitRatioNumbers)1502 void WindowRoot::SetSplitRatios(const std::vector<float>& splitRatioNumbers)
1503 {
1504     auto& splitRatios = splitRatioConfig_.splitRatios;
1505     splitRatios.clear();
1506     splitRatios = splitRatioNumbers;
1507     for (auto iter = splitRatios.begin(); iter != splitRatios.end();) {
1508         if (*iter > 0 && *iter < 1) { // valid ratio range (0, 1)
1509             iter++;
1510         } else {
1511             iter = splitRatios.erase(iter);
1512         }
1513     }
1514     std::sort(splitRatios.begin(), splitRatios.end());
1515     auto iter = std::unique(splitRatios.begin(), splitRatios.end());
1516     splitRatios.erase(iter, splitRatios.end()); // remove duplicate ratios
1517 }
1518 
SetExitSplitRatios(const std::vector<float> & exitSplitRatios)1519 void WindowRoot::SetExitSplitRatios(const std::vector<float>& exitSplitRatios)
1520 {
1521     if (exitSplitRatios.size() != 2) {
1522         return;
1523     }
1524     if (exitSplitRatios[0] > 0 && exitSplitRatios[0] < DEFAULT_SPLIT_RATIO) {
1525         splitRatioConfig_.exitSplitStartRatio = exitSplitRatios[0];
1526     }
1527     if (exitSplitRatios[1] > DEFAULT_SPLIT_RATIO && exitSplitRatios[1] < 1) {
1528         splitRatioConfig_.exitSplitEndRatio = exitSplitRatios[1];
1529     }
1530 }
1531 
GetModeChangeHotZones(DisplayId displayId,ModeChangeHotZones & hotZones,const ModeChangeHotZonesConfig & config)1532 WMError WindowRoot::GetModeChangeHotZones(DisplayId displayId,
1533     ModeChangeHotZones& hotZones, const ModeChangeHotZonesConfig& config)
1534 {
1535     auto container = GetOrCreateWindowNodeContainer(displayId);
1536     if (container == nullptr) {
1537         WLOGFE("GetModeChangeHotZones failed, window container could not be found");
1538         return WMError::WM_ERROR_NULLPTR;
1539     }
1540     container->GetModeChangeHotZones(displayId, hotZones, config);
1541     return WMError::WM_OK;
1542 }
1543 
RemoveSingleUserWindowNodes(int accountId)1544 void WindowRoot::RemoveSingleUserWindowNodes(int accountId)
1545 {
1546     std::vector<DisplayId> displayIds = GetAllDisplayIds();
1547     for (auto id : displayIds) {
1548         sptr<WindowNodeContainer> container = GetOrCreateWindowNodeContainer(id);
1549         if (container == nullptr) {
1550             WLOGFD("get container failed %{public}" PRIu64"", id);
1551             continue;
1552         }
1553         container->RemoveSingleUserWindowNodes(accountId);
1554     }
1555 }
1556 
UpdateRsTree(uint32_t windowId,bool isAdd)1557 WMError WindowRoot::UpdateRsTree(uint32_t windowId, bool isAdd)
1558 {
1559     sptr<WindowNode> node = GetWindowNode(windowId);
1560     if (node == nullptr) {
1561         WLOGFE("could not find window");
1562         return WMError::WM_ERROR_NULLPTR;
1563     }
1564     auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId());
1565     if (container == nullptr) {
1566         WLOGFE("window container could not be found");
1567         return WMError::WM_ERROR_NULLPTR;
1568     }
1569     for (auto& displayId : node->GetShowingDisplays()) {
1570         if (isAdd) {
1571             container->AddNodeOnRSTree(node, displayId, displayId, WindowUpdateType::WINDOW_UPDATE_ACTIVE);
1572         } else {
1573             container->RemoveNodeFromRSTree(node, displayId, displayId, WindowUpdateType::WINDOW_UPDATE_ACTIVE);
1574         }
1575     }
1576     RSTransaction::FlushImplicitTransaction();
1577     return WMError::WM_OK;
1578 }
1579 
FindDialogCallerNode(WindowType type,sptr<IRemoteObject> token)1580 sptr<WindowNode> WindowRoot::FindDialogCallerNode(WindowType type, sptr<IRemoteObject> token)
1581 {
1582     if (type != WindowType::WINDOW_TYPE_DIALOG) {
1583         return nullptr;
1584     }
1585 
1586     auto iter = std::find_if(windowNodeMap_.begin(), windowNodeMap_.end(),
1587         [token](const std::map<uint32_t, sptr<WindowNode>>::value_type& pair) {
1588             if (WindowHelper::IsMainWindow(pair.second->GetWindowType())) {
1589                 return pair.second->abilityToken_ == token;
1590             }
1591             return false;
1592         });
1593     if (iter == windowNodeMap_.end()) {
1594         WLOGFD("cannot find windowNode");
1595         return nullptr;
1596     }
1597     return iter->second;
1598 }
1599 
CheckMultiDialogWindows(WindowType type,sptr<IRemoteObject> token)1600 bool WindowRoot::CheckMultiDialogWindows(WindowType type, sptr<IRemoteObject> token)
1601 {
1602     if (type != WindowType::WINDOW_TYPE_DIALOG) {
1603         return false;
1604     }
1605 
1606     sptr<WindowNode> newCaller, oriCaller;
1607 
1608     newCaller = FindDialogCallerNode(type, token);
1609     if (newCaller == nullptr) {
1610         return false;
1611     }
1612 
1613     for (auto& iter : windowNodeMap_) {
1614         if (iter.second->GetWindowType() == WindowType::WINDOW_TYPE_DIALOG) {
1615             oriCaller = FindDialogCallerNode(iter.second->GetWindowType(), iter.second->dialogTargetToken_);
1616             if (oriCaller == newCaller) {
1617                 return true;
1618             }
1619         }
1620     }
1621 
1622     return false;
1623 }
1624 
OnRenderModeChanged(bool isUniRender)1625 void WindowRoot::OnRenderModeChanged(bool isUniRender)
1626 {
1627     WLOGFD("SwitchRender: render mode of RS has changed from %{public}u to %{public}s",
1628         static_cast<uint32_t>(renderMode_), std::to_string(isUniRender).c_str());
1629     if (isUniRender) {
1630         switch (renderMode_) {
1631             case RenderMode::SEPARATED:
1632             case RenderMode::UNIFYING:
1633                 renderMode_ = RenderMode::UNIFIED;
1634                 break;
1635             case RenderMode::SEPARATING:
1636                 RSInterfaces::GetInstance().UpdateRenderMode(false);
1637                 break;
1638             default:
1639                 WLOGFE("SwitchRender: impossible code");
1640                 break;
1641         }
1642     } else {
1643         switch (renderMode_) {
1644             case RenderMode::UNIFIED:
1645             case RenderMode::SEPARATING:
1646                 renderMode_ = RenderMode::SEPARATED;
1647                 break;
1648             case RenderMode::UNIFYING:
1649                 RSInterfaces::GetInstance().UpdateRenderMode(true);
1650                 break;
1651             default:
1652                 WLOGFE("SwitchRender: impossible code");
1653                 break;
1654         }
1655     }
1656 }
1657 
SwitchRenderModeIfNeeded()1658 void WindowRoot::SwitchRenderModeIfNeeded()
1659 {
1660     if (displayIdMap_.empty()) {
1661         WLOGFE("WindowRoot::SwitchRenderModeIfNeeded: displayIdMap_ is empty");
1662         return;
1663     }
1664     if (displayIdMap_.size() != 1) {
1665         WLOGFE("WindowRoot::SwitchRenderModeIfNeeded: invalid screenGroup number");
1666         return;
1667     }
1668     uint32_t displayNum = displayIdMap_.begin()->second.size();
1669     if (displayNum > 1) {
1670         // switch to sperate render mode
1671         ChangeRSRenderModeIfNeeded(false);
1672         return;
1673     }
1674 
1675     bool exceed = IsAppWindowExceed();
1676     if (exceed) {
1677         // switch to sperate render mode
1678         ChangeRSRenderModeIfNeeded(false);
1679     } else {
1680         // switch to unified render mode
1681         ChangeRSRenderModeIfNeeded(true);
1682     }
1683 }
1684 
ChangeRSRenderModeIfNeeded(bool isToUnified)1685 void WindowRoot::ChangeRSRenderModeIfNeeded(bool isToUnified)
1686 {
1687     switch (renderMode_) {
1688         case RenderMode::SEPARATED:
1689             if (isToUnified) {
1690                 WLOGFD("SwitchRender: notify RS from separated to be unifying");
1691                 renderMode_ = RenderMode::UNIFYING;
1692                 RSInterfaces::GetInstance().UpdateRenderMode(true);
1693             }
1694             break;
1695         case RenderMode::UNIFIED:
1696             if (!isToUnified) {
1697                 WLOGFD("SwitchRender: notify RS from unified to be separating");
1698                 renderMode_ = RenderMode::SEPARATING;
1699                 RSInterfaces::GetInstance().UpdateRenderMode(false);
1700             }
1701             break;
1702         case RenderMode::SEPARATING:
1703             if (isToUnified) {
1704                 WLOGFD("SwitchRender: notify RS from separating to be unifying");
1705                 renderMode_ = RenderMode::UNIFYING;
1706             }
1707             break;
1708         case RenderMode::UNIFYING:
1709             if (!isToUnified) {
1710                 WLOGFD("SwitchRender: notify RS from unifying to be separating");
1711                 renderMode_ = RenderMode::SEPARATING;
1712             }
1713             break;
1714         default:
1715             WLOGE("SwitchRender: impossible code");
1716             break;
1717     }
1718 }
1719 
IsAppWindowExceed() const1720 bool WindowRoot::IsAppWindowExceed() const
1721 {
1722     uint32_t appWindowNum = 0;
1723     for (const auto& it : windowNodeMap_) {
1724         WindowType winType = it.second->GetWindowType();
1725         WindowMode winMode = it.second->GetWindowMode();
1726         if (winMode == WindowMode::WINDOW_MODE_SPLIT_PRIMARY || winMode == WindowMode::WINDOW_MODE_SPLIT_SECONDARY) {
1727             return false;
1728         }
1729         if (winType >= WindowType::APP_WINDOW_BASE && winType < WindowType::APP_WINDOW_END &&
1730             it.second->currentVisibility_) {
1731             appWindowNum++;
1732         }
1733     }
1734     WLOGFD("SwitchRender: the number of app window is %{public}u", maxUniRenderAppWindowNumber_);
1735     return (appWindowNum > maxUniRenderAppWindowNumber_);
1736 }
1737 
GetWindowNodeByAbilityToken(const sptr<IRemoteObject> & abilityToken)1738 sptr<WindowNode> WindowRoot::GetWindowNodeByAbilityToken(const sptr<IRemoteObject>& abilityToken)
1739 {
1740     for (const auto& iter : windowNodeMap_) {
1741         if (iter.second != nullptr && iter.second->abilityToken_ == abilityToken) {
1742             return iter.second;
1743         }
1744     }
1745     WLOGFE("could not find required abilityToken!");
1746     return nullptr;
1747 }
1748 
TakeWindowPairSnapshot(DisplayId displayId)1749 bool WindowRoot::TakeWindowPairSnapshot(DisplayId displayId)
1750 {
1751     auto container = GetWindowNodeContainer(displayId);
1752     return container == nullptr ? false : container->TakeWindowPairSnapshot(displayId);
1753 }
1754 
ClearWindowPairSnapshot(DisplayId displayId)1755 void WindowRoot::ClearWindowPairSnapshot(DisplayId displayId)
1756 {
1757     auto container = GetWindowNodeContainer(displayId);
1758     if (container == nullptr) {
1759         WLOGFE("clear window pair snapshot failed, because container in null");
1760         return;
1761     }
1762     return container->ClearWindowPairSnapshot(displayId);
1763 }
1764 } // namespace Rosen
1765 } // namespace OHOS
1766