1 /*
2  * Copyright (c) 2021-2023 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_node_container.h"
17 
18 #include <ability_manager_client.h>
19 #include <algorithm>
20 #include <cinttypes>
21 #include <cmath>
22 #include <ctime>
23 #include <hitrace_meter.h>
24 #include <limits>
25 #include <transaction/rs_interfaces.h>
26 #include <transaction/rs_transaction.h>
27 #include <transaction/rs_sync_transaction_controller.h>
28 
29 #ifdef POWERMGR_DISPLAY_MANAGER_ENABLE
30 #include <display_power_mgr_client.h>
31 #endif
32 
33 #ifdef POWER_MANAGER_ENABLE
34 #include <power_mgr_client.h>
35 #endif
36 
37 #include "common_event_manager.h"
38 #include "dm_common.h"
39 #include "remote_animation.h"
40 #include "starting_window.h"
41 #include "window_helper.h"
42 #include "window_inner_manager.h"
43 #include "window_layout_policy_cascade.h"
44 #include "window_layout_policy_tile.h"
45 #include "window_manager_agent_controller.h"
46 #include "window_manager_hilog.h"
47 #include "window_manager_service.h"
48 #include "window_manager_service_utils.h"
49 #include "window_system_effect.h"
50 #include "wm_common.h"
51 #include "wm_common_inner.h"
52 
53 namespace OHOS {
54 namespace Rosen {
55 namespace {
56 constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "Container"};
57 constexpr int WINDOW_NAME_MAX_LENGTH = 10;
58 constexpr uint32_t MAX_BRIGHTNESS = 255;
59 constexpr uint32_t SPLIT_WINDOWS_CNT = 2;
60 constexpr uint32_t EXIT_SPLIT_POINTS_NUMBER = 2;
61 constexpr int UID_TRANSFROM_DIVISOR = 200000;
62 constexpr int UID_MIN = 100;
63 }
64 AnimationConfig WindowNodeContainer::animationConfig_;
65 bool WindowNodeContainer::isFloatWindowAboveFullWindow_ = false;
66 uint32_t WindowNodeContainer::maxMainFloatingWindowNumber_ = 100;
67 bool WindowNodeContainer::isAnimateTransactionEnabled_ = false;
68 WindowUIType WindowNodeContainer::windowUIType_ = WindowUIType::INVALID_WINDOW;
69 
WindowNodeContainer(const sptr<DisplayInfo>& displayInfo, ScreenId displayGroupId)70 WindowNodeContainer::WindowNodeContainer(const sptr<DisplayInfo>& displayInfo, ScreenId displayGroupId)
71 {
72     DisplayId displayId = displayInfo->GetDisplayId();
73 
74     // create and displayGroupInfo and displayGroupController
75     DisplayGroupInfo::GetInstance().Init(displayGroupId, displayInfo);
76     displayGroupController_ = new DisplayGroupController(this);
77     displayGroupController_->InitNewDisplay(displayId);
78 
79     // init layout policy
80     layoutPolicies_[WindowLayoutMode::CASCADE] = new WindowLayoutPolicyCascade(
81             displayGroupController_->displayGroupWindowTree_);
82     layoutPolicies_[WindowLayoutMode::TILE] = new WindowLayoutPolicyTile(
83         displayGroupController_->displayGroupWindowTree_);
84     layoutPolicy_ = layoutPolicies_[WindowLayoutMode::CASCADE];
85     layoutPolicy_->Launch();
86 
87     // set initial divider rect in windowPair
88     Rect initialDivRect = layoutPolicies_[WindowLayoutMode::CASCADE]->GetDividerRect(displayId);
89     auto windowPair = displayGroupController_->GetWindowPairByDisplayId(displayId);
90     if (windowPair != nullptr) {
91         windowPair->SetDividerRect(initialDivRect);
92     }
93 
94     // init avoidAreaController
95     avoidController_ = new AvoidAreaController(focusedWindow_);
96     WindowInnerManager::GetInstance().NotifyDisplayLimitRectChange(
97         DisplayGroupInfo::GetInstance().GetAllDisplayRects());
98     isAnimateTransactionEnabled_ = system::GetParameter("persist.window.animateTransaction.enabled", "1")  == "1";
99 }
100 
~WindowNodeContainer()101 WindowNodeContainer::~WindowNodeContainer()
102 {
103     Destroy();
104 }
105 
GetWindowCountByType(WindowType windowType)106 uint32_t WindowNodeContainer::GetWindowCountByType(WindowType windowType)
107 {
108     uint32_t windowNumber = 0;
109     auto counter = [&windowNumber, &windowType](sptr<WindowNode>& windowNode) {
110         if (windowNode->GetWindowType() == windowType && !windowNode->startingWindowShown_) {
111             ++windowNumber;
112         }
113     };
114     std::for_each(belowAppWindowNode_->children_.begin(), belowAppWindowNode_->children_.end(), counter);
115     std::for_each(appWindowNode_->children_.begin(), appWindowNode_->children_.end(), counter);
116     std::for_each(aboveAppWindowNode_->children_.begin(), aboveAppWindowNode_->children_.end(), counter);
117     return windowNumber;
118 }
119 
GetMainFloatingWindowCount()120 uint32_t WindowNodeContainer::GetMainFloatingWindowCount()
121 {
122     uint32_t windowNumber = 0;
123     auto counter = [&windowNumber](sptr<WindowNode>& windowNode) {
124         WindowType windowType = windowNode->GetWindowType();
125         WindowMode windowMode = windowNode->GetWindowMode();
126         if (WindowHelper::IsMainFloatingWindow(windowType, windowMode) &&
127             !windowNode->startingWindowShown_) {
128             ++windowNumber;
129         }
130     };
131     std::for_each(appWindowNode_->children_.begin(), appWindowNode_->children_.end(), counter);
132     std::for_each(aboveAppWindowNode_->children_.begin(), aboveAppWindowNode_->children_.end(), counter);
133     return windowNumber;
134 }
135 
AddWindowNodeOnWindowTree(sptr<WindowNode>& node, const sptr<WindowNode>& parentNode)136 WMError WindowNodeContainer::AddWindowNodeOnWindowTree(sptr<WindowNode>& node, const sptr<WindowNode>& parentNode)
137 {
138     sptr<WindowNode> root = FindRoot(node->GetWindowType());
139     if (root == nullptr && !(WindowHelper::IsSystemSubWindow(node->GetWindowType()) &&
140         parentNode != nullptr)) {
141         WLOGFE("root is nullptr!");
142         return WMError::WM_ERROR_NULLPTR;
143     }
144     node->requestedVisibility_ = true;
145     if (parentNode != nullptr) { // subwindow
146         if (WindowHelper::IsSystemSubWindow(node->GetWindowType()) ||
147             node->GetWindowType() == WindowType::WINDOW_TYPE_APP_COMPONENT) {
148             if (WindowHelper::IsSubWindow(parentNode->GetWindowType()) ||
149                 WindowHelper::IsSystemSubWindow(parentNode->GetWindowType()) ||
150                 parentNode->GetWindowType() == WindowType::WINDOW_TYPE_APP_COMPONENT ||
151                 parentNode->GetWindowType() == WindowType::WINDOW_TYPE_DIALOG) {
152                 // some times, dialog is a child window, so exclude
153                 WLOGFE("the parent of window cannot be any sub window");
154                 return WMError::WM_ERROR_INVALID_PARAM;
155             }
156         } else {
157             if (parentNode->parent_ != root &&
158                 !((parentNode->GetWindowFlags() & static_cast<uint32_t>(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED)) &&
159                 (parentNode->parent_ == aboveAppWindowNode_))) {
160                 WLOGFE("window type and parent window not match \
161                     or try to add subwindow to subwindow, which is forbidden");
162                 return WMError::WM_ERROR_INVALID_PARAM;
163             }
164         }
165         node->currentVisibility_ = parentNode->currentVisibility_;
166         node->parent_ = parentNode;
167     } else { // mainwindow
168         node->parent_ = root;
169         node->currentVisibility_ = true;
170         for (auto& child : node->children_) {
171             child->currentVisibility_ = child->requestedVisibility_;
172         }
173         if (WindowHelper::IsSystemBarWindow(node->GetWindowType())) {
174             displayGroupController_->sysBarNodeMaps_[node->GetDisplayId()][node->GetWindowType()] = node;
175         }
176     }
177     return WMError::WM_OK;
178 }
179 
ShowStartingWindow(sptr<WindowNode>& node)180 WMError WindowNodeContainer::ShowStartingWindow(sptr<WindowNode>& node)
181 {
182     if (node->currentVisibility_) {
183         WLOGFE("current window is visible, windowId: %{public}u", node->GetWindowId());
184         return WMError::WM_ERROR_INVALID_OPERATION;
185     }
186 
187     WMError res = AddWindowNodeOnWindowTree(node, nullptr);
188     if (res != WMError::WM_OK) {
189         return res;
190     }
191     UpdateWindowTree(node);
192     displayGroupController_->PreProcessWindowNode(node, WindowUpdateType::WINDOW_UPDATE_ADDED);
193     StartingWindow::AddNodeOnRSTree(node, layoutPolicy_->IsMultiDisplay());
194     AssignZOrder();
195     layoutPolicy_->PerformWindowLayout(node, WindowUpdateType::WINDOW_UPDATE_ADDED);
196     WLOGI("ShowStartingWindow windowId: %{public}u end", node->GetWindowId());
197     return WMError::WM_OK;
198 }
199 
IsTileRectSatisfiedWithSizeLimits(sptr<WindowNode>& node)200 WMError WindowNodeContainer::IsTileRectSatisfiedWithSizeLimits(sptr<WindowNode>& node)
201 {
202     if (layoutMode_ == WindowLayoutMode::TILE &&
203         !layoutPolicy_->IsTileRectSatisfiedWithSizeLimits(node)) {
204         WLOGFE("layoutMode is tile, default rect is not satisfied with size limits of window, windowId: %{public}u",
205             node->GetWindowId());
206         return WMError::WM_ERROR_INVALID_WINDOW_MODE_OR_SIZE;
207     }
208     return WMError::WM_OK;
209 }
210 
GetAnimationConfigRef()211 AnimationConfig& WindowNodeContainer::GetAnimationConfigRef()
212 {
213     return animationConfig_;
214 }
215 
LayoutWhenAddWindowNode(sptr<WindowNode>& node, bool afterAnimation)216 void WindowNodeContainer::LayoutWhenAddWindowNode(sptr<WindowNode>& node, bool afterAnimation)
217 {
218     if (afterAnimation) {
219         layoutPolicy_->PerformWindowLayout(node, WindowUpdateType::WINDOW_UPDATE_ADDED);
220         return;
221     }
222     WLOGFD("AddWindowNode Id:%{public}u, currState:%{public}u",
223         node->GetWindowId(), static_cast<uint32_t>(node->stateMachine_.GetCurrentState()));
224     if (WindowHelper::IsMainWindow(node->GetWindowType()) &&
225         RemoteAnimation::IsRemoteAnimationEnabledAndFirst(node->GetDisplayId()) &&
226         node->stateMachine_.IsShowAnimationPlaying()) {
227         // for first frame callback
228         auto winRect = node->GetWindowRect();
229         if (node->surfaceNode_) {
230             node->surfaceNode_->SetBounds(0, 0, winRect.width_, winRect.height_);
231             WLOGI("SetBounds id:%{public}u, rect:[%{public}d, %{public}d, %{public}u, %{public}u]",
232                 node->GetWindowId(), winRect.posX_, winRect.posY_, winRect.width_, winRect.height_);
233             layoutPolicy_->NotifyClientAndAnimation(node, winRect, WindowSizeChangeReason::UNDEFINED);
234         }
235     } else {
236         if (node->GetWindowProperty()->GetAnimationFlag() == static_cast<uint32_t>(WindowAnimation::CUSTOM) &&
237             WindowHelper::IsSystemWindow(node->GetWindowType())) {
238                 node->SetWindowSizeChangeReason(WindowSizeChangeReason::CUSTOM_ANIMATION_SHOW);
239         }
240         layoutPolicy_->PerformWindowLayout(node, WindowUpdateType::WINDOW_UPDATE_ADDED);
241     }
242 }
243 
AddWindowNode(sptr<WindowNode>& node, sptr<WindowNode>& parentNode, bool afterAnimation)244 WMError WindowNodeContainer::AddWindowNode(sptr<WindowNode>& node, sptr<WindowNode>& parentNode, bool afterAnimation)
245 {
246     if (!node->startingWindowShown_) { // window except main Window
247         WMError res = AddWindowNodeOnWindowTree(node, parentNode);
248         if (res != WMError::WM_OK) {
249             return res;
250         }
251         UpdateWindowTree(node);
252         displayGroupController_->PreProcessWindowNode(node, WindowUpdateType::WINDOW_UPDATE_ADDED);
253         // add node on RSTree
254         for (auto& displayId : node->GetShowingDisplays()) {
255             AddNodeOnRSTree(node, displayId, displayId, WindowUpdateType::WINDOW_UPDATE_ADDED,
256                 node->isPlayAnimationShow_);
257         }
258     } else { // only main app window has starting window
259         node->isPlayAnimationShow_ = false;
260         node->startingWindowShown_ = false;
261         AddAppSurfaceNodeOnRSTree(node);
262         ReZOrderShowWhenLockedWindowIfNeeded(node);
263         RaiseZOrderForAppWindow(node, parentNode);
264     }
265     auto windowPair = displayGroupController_->GetWindowPairByDisplayId(node->GetDisplayId());
266     if (windowPair == nullptr) {
267         WLOGFE("Window pair is nullptr");
268         return WMError::WM_ERROR_NULLPTR;
269     }
270     windowPair->UpdateIfSplitRelated(node);
271     if (node->IsSplitMode()) {
272         // raise the z-order of window pair
273         RaiseSplitRelatedWindowToTop(node);
274         if (isFloatWindowAboveFullWindow_ && !windowPair->IsDuringSplit()) {
275             ResetAllMainFloatingWindowZOrder(appWindowNode_);
276         }
277     }
278     MinimizeOldestMainFloatingWindow(node->GetWindowId());
279     AssignZOrder();
280     LayoutWhenAddWindowNode(node, afterAnimation);
281     NotifyIfAvoidAreaChanged(node, AvoidControlType::AVOID_NODE_ADD);
282     DumpScreenWindowTreeByWinId(node->GetWindowId());
283     UpdateCameraFloatWindowStatus(node, true);
284     if (WindowHelper::IsMainWindow(node->GetWindowType())) {
285         backupWindowIds_.clear();
286     }
287 
288     if (node->GetWindowType() == WindowType::WINDOW_TYPE_KEYGUARD) {
289         isScreenLocked_ = true;
290         SetBelowScreenlockVisible(node, false);
291     }
292     if (node->GetWindowType() == WindowType::WINDOW_TYPE_WALLPAPER) {
293         RemoteAnimation::NotifyAnimationUpdateWallpaper(node);
294     }
295     if (node->GetWindowType() == WindowType::WINDOW_TYPE_DESKTOP) {
296         DisplayManagerServiceInner::GetInstance().SetGravitySensorSubscriptionEnabled();
297     }
298     WLOGI("AddWindowNode Id: %{public}u end", node->GetWindowId());
299     RSInterfaces::GetInstance().SetAppWindowNum(GetAppWindowNum());
300     // update private window count and notify dms private status changed
301     if (node->GetWindowProperty()->GetPrivacyMode()) {
302         UpdatePrivateStateAndNotify();
303     }
304     if (WindowHelper::IsMainWindow(node->GetWindowType())) {
305         WindowInfoReporter::GetInstance().InsertShowReportInfo(node->abilityInfo_.bundleName_);
306     }
307     return WMError::WM_OK;
308 }
309 
UpdateRSTreeWhenShowingDisplaysChange(sptr<WindowNode>& node, const std::vector<DisplayId>& lastShowingDisplays)310 void WindowNodeContainer::UpdateRSTreeWhenShowingDisplaysChange(sptr<WindowNode>& node,
311     const std::vector<DisplayId>& lastShowingDisplays)
312 {
313     if (!layoutPolicy_->IsMultiDisplay()) {
314         return;
315     }
316 
317     // Update RSTree
318     auto curShowingDisplays = node->GetShowingDisplays();
319     for (auto& displayId : lastShowingDisplays) {
320         if (std::find(curShowingDisplays.begin(), curShowingDisplays.end(), displayId) == curShowingDisplays.end()) {
321             RemoveNodeFromRSTree(node, displayId, *(curShowingDisplays.begin()),
322                 WindowUpdateType::WINDOW_UPDATE_ACTIVE);
323             WLOGI("remove from RSTree : %{public}" PRIu64"", displayId);
324         }
325     }
326 
327     for (auto& displayId : curShowingDisplays) {
328         if (std::find(lastShowingDisplays.begin(), lastShowingDisplays.end(), displayId) == lastShowingDisplays.end()) {
329             AddNodeOnRSTree(node, displayId, displayId, WindowUpdateType::WINDOW_UPDATE_ACTIVE);
330             WLOGI("add on RSTree : %{public}" PRIu64"", displayId);
331         }
332     }
333 }
334 
UpdateWindowNode(sptr<WindowNode>& node, WindowUpdateReason reason)335 WMError WindowNodeContainer::UpdateWindowNode(sptr<WindowNode>& node, WindowUpdateReason reason)
336 {
337     // Get last displayId and last showing displays before layout
338     auto lastShowingDisplays = node->GetShowingDisplays();
339 
340     // PreProcess window node and layout node
341     displayGroupController_->PreProcessWindowNode(node, WindowUpdateType::WINDOW_UPDATE_ACTIVE);
342     if (WindowHelper::IsMainWindow(node->GetWindowType()) && WindowHelper::IsSwitchCascadeReason(reason)) {
343         SwitchLayoutPolicy(WindowLayoutMode::CASCADE, node->GetDisplayId());
344     }
345     layoutPolicy_->PerformWindowLayout(node, WindowUpdateType::WINDOW_UPDATE_ACTIVE);
346     displayGroupController_->PostProcessWindowNode(node);
347     // Get current displayId and showing displays, update RSTree and displayGroupWindowTree
348     UpdateRSTreeWhenShowingDisplaysChange(node, lastShowingDisplays);
349     NotifyIfAvoidAreaChanged(node, AvoidControlType::AVOID_NODE_UPDATE);
350     WLOGD("UpdateNode Id: %{public}u end", node->GetWindowId());
351     return WMError::WM_OK;
352 }
353 
RemoveWindowNodeFromWindowTree(sptr<WindowNode>& node)354 void WindowNodeContainer::RemoveWindowNodeFromWindowTree(sptr<WindowNode>& node)
355 {
356     // remove this node from parent
357     auto iter = std::find(node->parent_->children_.begin(), node->parent_->children_.end(), node);
358     if (iter != node->parent_->children_.end()) {
359         node->parent_->children_.erase(iter);
360     } else {
361         WLOGFE("can't find this node in parent");
362     }
363     node->parent_ = nullptr;
364 }
365 
RemoveFromRsTreeWhenRemoveWindowNode(sptr<WindowNode>& node, bool fromAnimation)366 void WindowNodeContainer::RemoveFromRsTreeWhenRemoveWindowNode(sptr<WindowNode>& node, bool fromAnimation)
367 {
368     if (fromAnimation || (RemoteAnimation::IsRemoteAnimationEnabledAndFirst(node->GetDisplayId()) &&
369         node->stateMachine_.IsHideAnimationPlaying())) {
370             WLOGFD("not remove from rs tree id:%{public}u", node->GetWindowId());
371             return;
372     }
373     // When RemoteAnimation exists, remove node from rs tree after animation
374     WLOGFD("Id:%{public}u, isPlayAnimationHide_:%{public}u", node->GetWindowId(),
375         static_cast<uint32_t>(node->isPlayAnimationHide_));
376     // subwindow or no remote animation also exit with animation
377     for (auto& displayId : node->GetShowingDisplays()) {
378         RemoveNodeFromRSTree(node, displayId, displayId, WindowUpdateType::WINDOW_UPDATE_REMOVED,
379             node->isPlayAnimationHide_);
380     }
381 }
382 
SetSurfaceNodeVisible(sptr<WindowNode>& node, int32_t topPriority, bool visible)383 void WindowNodeContainer::SetSurfaceNodeVisible(sptr<WindowNode>& node, int32_t topPriority, bool visible)
384 {
385     if (node == nullptr) {
386         return;
387     }
388     if (node->parent_ != nullptr && node->currentVisibility_) {
389         if (node->priority_ < topPriority && !WindowHelper::IsShowWhenLocked(node->GetWindowFlags()) &&
390             !WindowHelper::IsShowWhenLocked(node->parent_->GetWindowFlags())) {
391             auto surfaceNode = node->leashWinSurfaceNode_ != nullptr ? node->leashWinSurfaceNode_ : node->surfaceNode_;
392             if (surfaceNode) {
393                 surfaceNode->SetVisible(visible);
394             }
395         }
396     }
397     for (auto& childNode : node->children_) {
398         SetSurfaceNodeVisible(childNode, topPriority, visible);
399     }
400 }
401 
SetBelowScreenlockVisible(sptr<WindowNode>& node, bool visible)402 void WindowNodeContainer::SetBelowScreenlockVisible(sptr<WindowNode>& node, bool visible)
403 {
404     int32_t topPriority = zorderPolicy_->GetWindowPriority(WindowType::WINDOW_TYPE_KEYGUARD);
405     std::vector<sptr<WindowNode>> rootNodes = { belowAppWindowNode_, appWindowNode_, aboveAppWindowNode_ };
406     for (auto& node : rootNodes) {
407         SetSurfaceNodeVisible(node, topPriority, visible);
408     }
409 }
410 
RemoveWindowNode(sptr<WindowNode>& node, bool fromAnimation)411 WMError WindowNodeContainer::RemoveWindowNode(sptr<WindowNode>& node, bool fromAnimation)
412 {
413     if (node == nullptr) {
414         WLOGFE("window node or surface node is nullptr, invalid");
415         return WMError::WM_ERROR_DESTROYED_OBJECT;
416     }
417     if (node->parent_ == nullptr) {
418         WLOGFW("can't find parent of this node");
419     } else {
420         RemoveWindowNodeFromWindowTree(node);
421     }
422 
423     node->requestedVisibility_ = false;
424     node->currentVisibility_ = false;
425     RemoveFromRsTreeWhenRemoveWindowNode(node, fromAnimation);
426     node->isPlayAnimationHide_ = false;
427     displayGroupController_->UpdateDisplayGroupWindowTree();
428     layoutPolicy_->PerformWindowLayout(node, WindowUpdateType::WINDOW_UPDATE_REMOVED);
429     WindowMode lastMode = node->GetWindowMode();
430     if (HandleRemoveWindow(node) != WMError::WM_OK) {
431         return WMError::WM_ERROR_NULLPTR;
432     }
433     if (!WindowHelper::IsFloatingWindow(lastMode)) {
434         NotifyDockWindowStateChanged(node, true);
435     }
436     NotifyIfAvoidAreaChanged(node, AvoidControlType::AVOID_NODE_REMOVE);
437     DumpScreenWindowTreeByWinId(node->GetWindowId());
438     UpdateCameraFloatWindowStatus(node, false);
439     if (node->GetWindowType() == WindowType::WINDOW_TYPE_KEYGUARD) {
440         isScreenLocked_ = false;
441         SetBelowScreenlockVisible(node, true);
442     }
443     WLOGI("Remove Id: %{public}u end", node->GetWindowId());
444     RSInterfaces::GetInstance().SetAppWindowNum(GetAppWindowNum());
445 
446     // update private window count and notify dms private status changed
447     if (node->GetWindowProperty()->GetPrivacyMode()) {
448         UpdatePrivateStateAndNotify();
449     }
450     if (WindowHelper::IsMainWindow(node->GetWindowType())) {
451         WindowInfoReporter::GetInstance().InsertHideReportInfo(node->abilityInfo_.bundleName_);
452     }
453     HandleRemoveWindowDisplayOrientation(node, fromAnimation);
454     return WMError::WM_OK;
455 }
456 
HandleRemoveWindowDisplayOrientation(sptr<WindowNode>& node, bool fromAnimation)457 void WindowNodeContainer::HandleRemoveWindowDisplayOrientation(sptr<WindowNode>& node, bool fromAnimation)
458 {
459     if (node->GetWindowMode() != WindowMode::WINDOW_MODE_FULLSCREEN) {
460         WLOGFD("[FixOrientation] not full screen window remove, do not update orientation");
461         return;
462     }
463     if (!FIX_ORIENTATION_ENABLE) {
464         auto nextRotatableWindow = GetNextRotatableWindow(node->GetWindowId());
465         if (nextRotatableWindow != nullptr) {
466             SetDisplayOrientationFromWindow(nextRotatableWindow, true);
467         }
468         return;
469     }
470     if (!fromAnimation) {
471         if (node->stateMachine_.IsHideAnimationPlaying()) {
472             WLOGFD("[FixOrientation] removing window is playing hide animation, do not update display orientation");
473             return;
474         }
475         auto nextRotatableWindow = GetNextRotatableWindow(node->GetWindowId());
476         if (nextRotatableWindow == nullptr) {
477             WLOGFD("[FixOrientation] no next window, do not update display orientation");
478             return;
479         }
480         WLOGFD("[FixOrientation] nexi rotatable window: %{public}u", nextRotatableWindow->GetWindowId());
481         if (nextRotatableWindow->stateMachine_.IsShowAnimationPlaying()) {
482             WLOGFD("[FixOrientation] next window is playing show animation, do not update display orientation");
483             return;
484         }
485         if (WmsUtils::IsFixedOrientation(nextRotatableWindow->GetRequestedOrientation(),
486             nextRotatableWindow->GetWindowMode(), nextRotatableWindow->GetWindowFlags())) {
487             WLOGFI("[FixOrientation] next rotatable window is fixed, do not animation");
488             SetDisplayOrientationFromWindow(nextRotatableWindow, false);
489         } else {
490             SetDisplayOrientationFromWindow(nextRotatableWindow, true);
491         }
492     }
493 }
494 
SetDisplayOrientationFromWindow(sptr<WindowNode>& node, bool withAnimation)495 void WindowNodeContainer::SetDisplayOrientationFromWindow(sptr<WindowNode>& node, bool withAnimation)
496 {
497     DisplayManagerServiceInner::GetInstance().SetOrientationFromWindow(node->GetDisplayId(),
498         node->GetRequestedOrientation(), withAnimation);
499 }
500 
UpdatePrivateStateAndNotify()501 void WindowNodeContainer::UpdatePrivateStateAndNotify()
502 {
503     uint32_t prePrivateWindowCount = privateWindowCount_;
504     WLOGFD("before update : privateWindow count: %{public}u", prePrivateWindowCount);
505     UpdatePrivateWindowCount();
506     if (prePrivateWindowCount == 0 && privateWindowCount_ == 1) {
507         DisplayManagerServiceInner::GetInstance().NotifyPrivateWindowStateChanged(true);
508     } else if (prePrivateWindowCount == 1 && privateWindowCount_ == 0) {
509         DisplayManagerServiceInner::GetInstance().NotifyPrivateWindowStateChanged(false);
510     }
511 }
512 
UpdatePrivateWindowCount()513 void WindowNodeContainer::UpdatePrivateWindowCount()
514 {
515     std::vector<sptr<WindowNode>> windowNodes;
516     TraverseContainer(windowNodes);
517     uint32_t count = 0;
518     for (const auto& node : windowNodes) {
519         if (node->GetWindowProperty()->GetPrivacyMode()) {
520             ++count;
521         }
522     }
523     privateWindowCount_ = count;
524     WLOGFD("after update : privateWindow count: %{public}u", privateWindowCount_);
525 }
526 
GetAppWindowNum()527 uint32_t WindowNodeContainer::GetAppWindowNum()
528 {
529     uint32_t num = 0;
530     for (auto& child : appWindowNode_->children_) {
531         if (WindowHelper::IsAppWindow(child->GetWindowType())) {
532             num++;
533         }
534     }
535     return num;
536 }
537 
SetConfigMainFloatingWindowAbove(bool isAbove)538 void WindowNodeContainer::SetConfigMainFloatingWindowAbove(bool isAbove)
539 {
540     isFloatWindowAboveFullWindow_ = isAbove;
541 }
542 
SetMaxMainFloatingWindowNumber(uint32_t maxNumber)543 void WindowNodeContainer::SetMaxMainFloatingWindowNumber(uint32_t maxNumber)
544 {
545     maxMainFloatingWindowNumber_ = maxNumber;
546 }
547 
ResetMainFloatingWindowPriorityIfNeeded(sptr<WindowNode>& windowNode)548 void WindowNodeContainer::ResetMainFloatingWindowPriorityIfNeeded(sptr<WindowNode>& windowNode)
549 {
550     if (!isFloatWindowAboveFullWindow_) {
551         return;
552     }
553     const WindowType& windowType = windowNode->GetWindowType();
554     const WindowMode& windowMode = windowNode->GetWindowMode();
555     if (!WindowHelper::IsMainFloatingWindow(windowType, windowMode)) {
556         return;
557     }
558     const int32_t priorityOffset = 1;
559     auto baseZOrderPolicy = zorderPolicy_->GetWindowPriority(windowType);
560     if (isScreenLocked_ &&
561         (windowNode->GetWindowFlags() & static_cast<uint32_t>(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED))) {
562         // if window show when lock, priority should bigger than KEYGUARD.
563         baseZOrderPolicy = zorderPolicy_->GetWindowPriority(WindowType::WINDOW_TYPE_KEYGUARD) + 1;
564     }
565 
566     auto windowPair = displayGroupController_->GetWindowPairByDisplayId(windowNode->GetDisplayId());
567     if (windowPair != nullptr && windowPair->IsDuringSplit()) {
568         windowNode->priority_ = baseZOrderPolicy - priorityOffset;
569         WLOGFD("Reset floating main window zorder priority.[windowId: %{public}u, priority: %{public}d] ",
570             windowNode->GetWindowId(), windowNode->priority_);
571         return;
572     }
573 
574     windowNode->priority_ = baseZOrderPolicy + priorityOffset;
575     WLOGFD("Reset floating main window zorder priority.[windowId: %{public}u, priority: %{public}d] ",
576         windowNode->GetWindowId(), windowNode->priority_);
577 }
578 
ResetAllMainFloatingWindowZOrder(sptr<WindowNode>& rootNode)579 void WindowNodeContainer::ResetAllMainFloatingWindowZOrder(sptr<WindowNode>& rootNode)
580 {
581     if (!isFloatWindowAboveFullWindow_) {
582         WLOGFD("The free window level above full screen window feature is turned off");
583         return;
584     }
585     if (rootNode != appWindowNode_ && rootNode != aboveAppWindowNode_) {
586         return;
587     }
588     /*
589      * update all mainFloatingWindow position on window tree with
590      * the same raleative position between mainFloatingWindows.
591      */
592     std::vector<sptr<WindowNode>> tempWindows;
593     auto itor = rootNode->children_.begin();
594     while (itor != rootNode->children_.end()) {
595         const WindowType& windowType = (*itor)->GetWindowType();
596         const WindowMode& windowMode = (*itor)->GetWindowMode();
597         if (WindowHelper::IsMainFloatingWindow(windowType, windowMode)) {
598             tempWindows.push_back(*itor);
599             itor = rootNode->children_.erase(itor);
600         } else {
601             itor++;
602         }
603     }
604 
605     for (auto& node : tempWindows) {
606         UpdateWindowTree(node);
607     }
608 }
609 
HandleRemoveWindow(sptr<WindowNode>& node)610 WMError WindowNodeContainer::HandleRemoveWindow(sptr<WindowNode>& node)
611 {
612     WLOGFD("start");
613     auto windowPair = displayGroupController_->GetWindowPairByDisplayId(node->GetDisplayId());
614     if (windowPair == nullptr) {
615         WLOGFE("Window pair is nullptr");
616         return WMError::WM_ERROR_NULLPTR;
617     }
618     windowPair->HandleRemoveWindow(node);
619     auto dividerWindow = windowPair->GetDividerWindow();
620     auto type = node->GetWindowType();
621     if ((type == WindowType::WINDOW_TYPE_STATUS_BAR || type == WindowType::WINDOW_TYPE_NAVIGATION_BAR) &&
622         dividerWindow != nullptr) {
623         UpdateWindowNode(dividerWindow, WindowUpdateReason::UPDATE_RECT);
624     }
625     WLOGFD("end");
626     return WMError::WM_OK;
627 }
628 
DestroyWindowNode(sptr<WindowNode>& node, std::vector<uint32_t>& windowIds)629 WMError WindowNodeContainer::DestroyWindowNode(sptr<WindowNode>& node, std::vector<uint32_t>& windowIds)
630 {
631     WMError ret = RemoveWindowNode(node);
632     if (ret != WMError::WM_OK) {
633         WLOGFE("RemoveWindowNode failed");
634         return ret;
635     }
636     StartingWindow::ReleaseStartWinSurfaceNode(node);
637     node->surfaceNode_ = nullptr;
638     windowIds.push_back(node->GetWindowId());
639     for (auto& child : node->children_) { // destroy sub window if exists
640         windowIds.push_back(child->GetWindowId());
641         child->parent_ = nullptr;
642         if (child->surfaceNode_ != nullptr) {
643             WLOGI("child surfaceNode set nullptr");
644             child->surfaceNode_ = nullptr;
645         }
646     }
647 
648     // clear vector cache completely, swap with empty vector
649     auto emptyVector = std::vector<sptr<WindowNode>>();
650     node->children_.swap(emptyVector);
651     if (node->GetWindowType() == WindowType::WINDOW_TYPE_WALLPAPER) {
652         RemoteAnimation::NotifyAnimationUpdateWallpaper(nullptr);
653     }
654     if (WindowHelper::IsMainWindow(node->GetWindowType())) {
655         WindowInfoReporter::GetInstance().InsertDestroyReportInfo(node->abilityInfo_.bundleName_);
656     }
657 
658     UpdateAvoidAreaListener(node, false);
659     WLOGI("DestroyNode Id: %{public}u end", node->GetWindowId());
660     return WMError::WM_OK;
661 }
662 
UpdateSizeChangeReason(sptr<WindowNode>& node, WindowSizeChangeReason reason)663 void WindowNodeContainer::UpdateSizeChangeReason(sptr<WindowNode>& node, WindowSizeChangeReason reason)
664 {
665     if (!node->GetWindowToken()) {
666         WLOGFE("windowToken is null");
667         return;
668     }
669     if (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) {
670         for (auto& child : appWindowNode_->children_) {
671             if (child->IsSplitMode() && child->GetWindowToken()) {
672                 layoutPolicy_->NotifyClientAndAnimation(child, child->GetWindowRect(), reason);
673                 WLOGI("Notify split window that drag is start or end, Id: "
674                     "%{public}d, reason: %{public}u", child->GetWindowId(), reason);
675             }
676         }
677     } else {
678         layoutPolicy_->NotifyClientAndAnimation(node, node->GetWindowRect(), reason);
679         WLOGI("Notify window that drag is start or end, windowId: %{public}d, "
680             "reason: %{public}u", node->GetWindowId(), reason);
681     }
682 }
683 
UpdateWindowTree(sptr<WindowNode>& node)684 void WindowNodeContainer::UpdateWindowTree(sptr<WindowNode>& node)
685 {
686     HITRACE_METER(HITRACE_TAG_WINDOW_MANAGER);
687     node->priority_ = zorderPolicy_->GetWindowPriority(node->GetWindowType());
688     RaiseInputMethodWindowPriorityIfNeeded(node);
689     RaiseShowWhenLockedWindowIfNeeded(node);
690     ResetMainFloatingWindowPriorityIfNeeded(node);
691     auto parentNode = node->parent_;
692     if (parentNode == nullptr) {
693         WLOGI("Current window node has no parent: %{public}u", node->GetWindowId());
694         return;
695     }
696     auto iter = std::find(parentNode->children_.begin(), parentNode->children_.end(), node);
697     if (iter != parentNode->children_.end()) {
698         WLOGI("node %{public}u already on window tree, not update!", node->GetWindowId());
699         return;
700     }
701     auto position = parentNode->children_.end();
702     int splitWindowCnt = 0;
703     for (auto child = parentNode->children_.begin(); child < parentNode->children_.end(); ++child) {
704         if (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE && splitWindowCnt == SPLIT_WINDOWS_CNT) {
705             position = child;
706             break;
707         }
708         if (WindowHelper::IsSplitWindowMode((*child)->GetWindowMode())) {
709             splitWindowCnt++;
710         }
711         if ((*child)->priority_ > node->priority_) {
712             position = child;
713             break;
714         }
715     }
716     parentNode->children_.insert(position, node);
717 }
718 
AddAppSurfaceNodeOnRSTree(sptr<WindowNode>& node)719 bool WindowNodeContainer::AddAppSurfaceNodeOnRSTree(sptr<WindowNode>& node)
720 {
721     /*
722      * App main window must has starting window, and show after starting window
723      * Starting Window has already update leashWindowSurfaceNode and starting window surfaceNode on RSTree
724      * Just need add appSurface Node as child of leashWindowSurfaceNode
725      */
726     HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "AddAppSurfaceNodeOnRSTree(%u)", node->GetWindowId());
727     if (!WindowHelper::IsMainWindow(node->GetWindowType())) {
728         WLOGFE("id:%{public}u not main app window but has start window", node->GetWindowId());
729         return false;
730     }
731     if (!node->leashWinSurfaceNode_ || !node->surfaceNode_) {
732         WLOGFE("id:%{public}u leashWinSurfaceNode or surfaceNode is null but has start window!", node->GetWindowId());
733         return false;
734     }
735     WLOGI("AddAppSurfaceNodeOnRSTree Id: %{public}d", node->GetWindowId());
736     if (!node->currentVisibility_) {
737         WLOGI("id: %{public}d is invisible, no need update RS tree", node->GetWindowId());
738         return false;
739     }
740     node->leashWinSurfaceNode_->AddChild(node->surfaceNode_, -1);
741     return true;
742 }
743 
OpenInputMethodSyncTransaction()744 void WindowNodeContainer::OpenInputMethodSyncTransaction()
745 {
746     if (!isAnimateTransactionEnabled_) {
747         WLOGD("InputMethodSyncTransaction is not enabled");
748         return;
749     }
750     // Before open transaction, it must flush first.
751     auto transactionProxy = RSTransactionProxy::GetInstance();
752     if (!transactionProxy) {
753         return;
754     }
755     transactionProxy->FlushImplicitTransaction();
756     auto syncTransactionController = RSSyncTransactionController::GetInstance();
757     if (syncTransactionController) {
758         syncTransactionController->OpenSyncTransaction();
759     }
760     WLOGD("OpenInputMethodSyncTransaction");
761 }
762 
CloseInputMethodSyncTransaction()763 void WindowNodeContainer::CloseInputMethodSyncTransaction()
764 {
765     if (!isAnimateTransactionEnabled_) {
766         WLOGD("InputMethodSyncTransaction is not enabled while close");
767         return;
768     }
769     auto syncTransactionController = RSSyncTransactionController::GetInstance();
770     if (syncTransactionController) {
771         syncTransactionController->CloseSyncTransaction();
772     }
773     WLOGD("CloseInputMethodSyncTransaction");
774 }
775 
IsWindowFollowParent(WindowType type)776 bool WindowNodeContainer::IsWindowFollowParent(WindowType type)
777 {
778     if (windowUIType_ != WindowUIType::PHONE_WINDOW) {
779         return false;
780     }
781     return WindowHelper::IsWindowFollowParent(type);
782 }
783 
AddNodeOnRSTree(sptr<WindowNode>& node, DisplayId displayId, DisplayId parentDisplayId, WindowUpdateType type, bool animationPlayed)784 bool WindowNodeContainer::AddNodeOnRSTree(sptr<WindowNode>& node, DisplayId displayId, DisplayId parentDisplayId,
785     WindowUpdateType type, bool animationPlayed)
786 {
787     HITRACE_METER(HITRACE_TAG_WINDOW_MANAGER);
788     if (node->GetWindowProperty()->GetAnimationFlag() == static_cast<uint32_t>(WindowAnimation::CUSTOM) ||
789         node->GetWindowType() == WindowType::WINDOW_TYPE_APP_COMPONENT) {
790         WLOGI("no need to update RSTree");
791         return true;
792     }
793     bool isMultiDisplay = layoutPolicy_->IsMultiDisplay();
794     WLOGFD("Id: %{public}d, displayId: %{public}" PRIu64", parentDisplayId: %{public}" PRIu64", "
795         "isMultiDisplay: %{public}d, animationPlayed: %{public}d",
796         node->GetWindowId(), displayId, parentDisplayId, isMultiDisplay, animationPlayed);
797     auto updateRSTreeFunc = [&]() {
798         if (!node->currentVisibility_) {
799             WLOGI("id: %{public}d invisible, no need update RS tree", node->GetWindowId());
800             return;
801         }
802 
803         if (IsWindowFollowParent(node->GetWindowType())) {
804             auto& parentNode = node->parent_;
805             if (parentNode != nullptr && parentNode->surfaceNode_ != nullptr &&
806                 node->surfaceNode_ != nullptr) {
807                 node->surfaceNode_->SetTranslateX(node->GetWindowRect().posX_ - parentNode->GetWindowRect().posX_);
808                 node->surfaceNode_->SetTranslateY(node->GetWindowRect().posY_ - parentNode->GetWindowRect().posY_);
809                 node->surfaceNode_->SetVisible(true);
810                 parentNode->surfaceNode_->AddChild(node->surfaceNode_, -1);
811                 WLOGFD("Add surfaceNode to parent surfaceNode succeed.");
812                 return;
813             }
814         }
815         auto& dms = DisplayManagerServiceInner::GetInstance();
816         auto& surfaceNode = node->leashWinSurfaceNode_ != nullptr ? node->leashWinSurfaceNode_ : node->surfaceNode_;
817         dms.UpdateRSTree(displayId, parentDisplayId, surfaceNode, true, isMultiDisplay);
818         for (auto& child : node->children_) {
819             if (child->currentVisibility_ && !IsWindowFollowParent(child->GetWindowType())) {
820                 dms.UpdateRSTree(displayId, parentDisplayId, child->surfaceNode_, true, isMultiDisplay);
821             }
822         }
823     };
824 
825     if (type != WindowUpdateType::WINDOW_UPDATE_ADDED && type != WindowUpdateType::WINDOW_UPDATE_REMOVED) {
826         updateRSTreeFunc();
827         return true;
828     }
829 
830     WindowGravity windowGravity;
831     uint32_t percent;
832     node->GetWindowGravity(windowGravity, percent);
833     if (node->EnableDefaultAnimation(animationPlayed)) {
834         WLOGFD("Add node with animation");
835         StartTraceArgs(HITRACE_TAG_WINDOW_MANAGER, "Animate(%u)", node->GetWindowId());
836         RSNode::Animate(animationConfig_.windowAnimationConfig_.animationTiming_.timingProtocol_,
837             animationConfig_.windowAnimationConfig_.animationTiming_.timingCurve_, updateRSTreeFunc);
838         FinishTrace(HITRACE_TAG_WINDOW_MANAGER);
839     } else if (node->GetWindowType() == WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT &&
840         windowGravity != WindowGravity::WINDOW_GRAVITY_FLOAT &&
841         !animationPlayed) { // add keyboard with animation
842         auto timingProtocol = animationConfig_.keyboardAnimationIn_.duration_;
843         OpenInputMethodSyncTransaction();
844         RSNode::Animate(timingProtocol, animationConfig_.keyboardAnimationIn_.curve_, updateRSTreeFunc);
845         CloseInputMethodSyncTransaction();
846     } else {
847         WLOGFD("add node without animation");
848         updateRSTreeFunc();
849     }
850     return true;
851 }
852 
RemoveNodeFromRSTree(sptr<WindowNode>& node, DisplayId displayId, DisplayId parentDisplayId, WindowUpdateType type, bool animationPlayed)853 bool WindowNodeContainer::RemoveNodeFromRSTree(sptr<WindowNode>& node, DisplayId displayId, DisplayId parentDisplayId,
854     WindowUpdateType type, bool animationPlayed)
855 {
856     HITRACE_METER(HITRACE_TAG_WINDOW_MANAGER);
857     if (node->GetWindowProperty()->GetAnimationFlag() == static_cast<uint32_t>(WindowAnimation::CUSTOM) ||
858         node->GetWindowType() == WindowType::WINDOW_TYPE_APP_COMPONENT) {
859         WLOGI("no need to update RSTree");
860         return true;
861     }
862     bool isMultiDisplay = layoutPolicy_->IsMultiDisplay();
863     WLOGFD("Id: %{public}d, displayId: %{public}" PRIu64", isMultiDisplay: %{public}d, "
864         "parentDisplayId: %{public}" PRIu64", animationPlayed: %{public}d",
865         node->GetWindowId(), displayId, isMultiDisplay, parentDisplayId, animationPlayed);
866     auto updateRSTreeFunc = [&]() {
867         if (IsWindowFollowParent(node->GetWindowType())) {
868             const auto& parentNode = node->parent_;
869             if (parentNode != nullptr && parentNode->surfaceNode_ != nullptr &&
870                 node->surfaceNode_ != nullptr) {
871                 node->surfaceNode_->SetVisible(false);
872                 parentNode->surfaceNode_->RemoveChild(node->surfaceNode_);
873                 WLOGFD("Remove surfaceNode to parent surfaceNode succeed.");
874                 return;
875             }
876         }
877         auto& dms = DisplayManagerServiceInner::GetInstance();
878         auto& surfaceNode = node->leashWinSurfaceNode_ != nullptr ? node->leashWinSurfaceNode_ : node->surfaceNode_;
879         dms.UpdateRSTree(displayId, parentDisplayId, surfaceNode, false, isMultiDisplay);
880         for (auto& child : node->children_) {
881             if (child->currentVisibility_ && !IsWindowFollowParent(child->GetWindowType())) {
882                 dms.UpdateRSTree(displayId, parentDisplayId, child->surfaceNode_, false, isMultiDisplay);
883             }
884         }
885     };
886 
887     if (type != WindowUpdateType::WINDOW_UPDATE_ADDED && type != WindowUpdateType::WINDOW_UPDATE_REMOVED) {
888         updateRSTreeFunc();
889         return true;
890     }
891 
892     WindowGravity windowGravity;
893     uint32_t percent;
894     node->GetWindowGravity(windowGravity, percent);
895     if (node->EnableDefaultAnimation(animationPlayed)) {
896         WLOGFD("remove with animation");
897         StartTraceArgs(HITRACE_TAG_WINDOW_MANAGER, "Animate(%u)", node->GetWindowId());
898         if (node->surfaceNode_) {
899             node->surfaceNode_->SetFreeze(true);
900         }
901         wptr<WindowNode> weakNode(node);
902         RSNode::Animate(animationConfig_.windowAnimationConfig_.animationTiming_.timingProtocol_,
903             animationConfig_.windowAnimationConfig_.animationTiming_.timingCurve_, updateRSTreeFunc, [weakNode]() {
904             auto weakWindow = weakNode.promote();
905             if (weakWindow && weakWindow->surfaceNode_) {
906                 weakWindow->surfaceNode_->SetFreeze(false);
907             }
908         });
909         FinishTrace(HITRACE_TAG_WINDOW_MANAGER);
910     } else if (node->GetWindowType() == WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT &&
911         windowGravity != WindowGravity::WINDOW_GRAVITY_FLOAT && !animationPlayed) {
912         // remove keyboard with animation
913         OpenInputMethodSyncTransaction();
914         auto timingProtocol = animationConfig_.keyboardAnimationOut_.duration_;
915         RSNode::Animate(timingProtocol, animationConfig_.keyboardAnimationOut_.curve_, updateRSTreeFunc);
916         CloseInputMethodSyncTransaction();
917     } else {
918         updateRSTreeFunc();
919     }
920     return true;
921 }
922 
Destroy()923 const std::vector<uint32_t>& WindowNodeContainer::Destroy()
924 {
925     // clear vector cache completely, swap with empty vector
926     auto emptyVector = std::vector<uint32_t>();
927     removedIds_.swap(emptyVector);
928     for (auto& node : belowAppWindowNode_->children_) {
929         DestroyWindowNode(node, removedIds_);
930     }
931     for (auto& node : appWindowNode_->children_) {
932         DestroyWindowNode(node, removedIds_);
933     }
934     for (auto& node : aboveAppWindowNode_->children_) {
935         DestroyWindowNode(node, removedIds_);
936     }
937     return removedIds_;
938 }
939 
FindRoot(WindowType type) const940 sptr<WindowNode> WindowNodeContainer::FindRoot(WindowType type) const
941 {
942     if (WindowHelper::IsAppWindow(type) || type == WindowType::WINDOW_TYPE_DOCK_SLICE ||
943         type == WindowType::WINDOW_TYPE_APP_COMPONENT || type == WindowType::WINDOW_TYPE_PLACEHOLDER ||
944         type == WindowType::WINDOW_TYPE_DIALOG) {
945         return appWindowNode_;
946     }
947     if (WindowHelper::IsBelowSystemWindow(type)) {
948         return belowAppWindowNode_;
949     }
950     if (WindowHelper::IsAboveSystemWindow(type)) {
951         return aboveAppWindowNode_;
952     }
953     return nullptr;
954 }
955 
FindWindowNodeById(uint32_t id) const956 sptr<WindowNode> WindowNodeContainer::FindWindowNodeById(uint32_t id) const
957 {
958     std::vector<sptr<WindowNode>> rootNodes = { aboveAppWindowNode_, appWindowNode_, belowAppWindowNode_ };
959     for (const auto& rootNode : rootNodes) {
960         for (auto& node : rootNode->children_) {
961             if (node->GetWindowId() == id) {
962                 return node;
963             }
964             for (auto& subNode : node->children_) {
965                 if (subNode->GetWindowId() == id) {
966                     return subNode;
967                 }
968             }
969         }
970     }
971     return nullptr;
972 }
973 
UpdateFocusStatus(uint32_t id, bool focused)974 void WindowNodeContainer::UpdateFocusStatus(uint32_t id, bool focused)
975 {
976     auto node = FindWindowNodeById(id);
977     if (node == nullptr) {
978         WLOGFW("cannot find focused window id:%{public}d", id);
979         return;
980     }
981     if (focused) {
982         focusedPid_ = node->GetCallingPid();
983     }
984     node->isFocused_ = focused;
985     // change focus window shadow
986     WindowSystemEffect::SetWindowShadow(node);
987     if (node->GetCallingPid() == 0) {
988         WLOGFW("focused window is starting window, no need notify");
989         return;
990     }
991 
992     if (focused && node->GetWindowProperty() != nullptr) {
993         AbilityInfo info = node->GetWindowProperty()->GetAbilityInfo();
994         WLOGFD("current focus window: windowId: %{public}d, windowName: %{public}s, bundleName: %{public}s,"
995             " abilityName: %{public}s, pid: %{public}d, uid: %{public}d", id,
996             node->GetWindowProperty()->GetWindowName().c_str(), info.bundleName_.c_str(), info.abilityName_.c_str(),
997             node->GetCallingPid(), node->GetCallingUid());
998         uint64_t focusNodeId = 0; // 0 means invalid
999         if (node->surfaceNode_ == nullptr) {
1000             WLOGFW("focused window surfaceNode is null");
1001         } else {
1002             focusNodeId = node->surfaceNode_->GetId();
1003         }
1004         FocusAppInfo appInfo =
1005             { node->GetCallingPid(), node->GetCallingUid(), info.bundleName_, info.abilityName_, focusNodeId };
1006         RSInterfaces::GetInstance().SetFocusAppInfo(appInfo);
1007     }
1008     if (node->GetWindowToken()) {
1009         node->GetWindowToken()->UpdateFocusStatus(focused);
1010     }
1011     if (node->abilityToken_ == nullptr) {
1012         WLOGW("AbilityToken is null, window : %{public}d", id);
1013     }
1014     sptr<FocusChangeInfo> focusChangeInfo = new FocusChangeInfo(node->GetWindowId(), node->GetDisplayId(),
1015         node->GetCallingPid(), node->GetCallingUid(), node->GetWindowType(), node->abilityToken_);
1016     WindowManagerAgentController::GetInstance().UpdateFocusChangeInfo(
1017         focusChangeInfo, focused);
1018 }
1019 
UpdateActiveStatus(uint32_t id, bool isActive)1020 void WindowNodeContainer::UpdateActiveStatus(uint32_t id, bool isActive)
1021 {
1022     auto node = FindWindowNodeById(id);
1023     if (node == nullptr) {
1024         WLOGFE("cannot find active window id: %{public}d", id);
1025         return;
1026     }
1027     if (isActive) {
1028         activePid_ = node->GetCallingPid();
1029     }
1030     if (node->GetWindowToken()) {
1031         node->GetWindowToken()->UpdateActiveStatus(isActive);
1032     }
1033 }
1034 
UpdateBrightness(uint32_t id, bool byRemoved)1035 void WindowNodeContainer::UpdateBrightness(uint32_t id, bool byRemoved)
1036 {
1037     auto node = FindWindowNodeById(id);
1038     if (node == nullptr) {
1039         WLOGFE("cannot find active window id: %{public}d", id);
1040         return;
1041     }
1042 
1043     if (!byRemoved) {
1044         if (!WindowHelper::IsAppWindow(node->GetWindowType())) {
1045             return;
1046         }
1047     }
1048     WLOGI("Brightness: [%{public}f, %{public}f]", GetDisplayBrightness(), node->GetBrightness());
1049     if (std::fabs(node->GetBrightness() - UNDEFINED_BRIGHTNESS) < std::numeric_limits<float>::min()) {
1050         if (GetDisplayBrightness() != node->GetBrightness()) {
1051             WLOGI("adjust brightness with default value");
1052 #ifdef POWERMGR_DISPLAY_MANAGER_ENABLE
1053             DisplayPowerMgr::DisplayPowerMgrClient::GetInstance().RestoreBrightness();
1054 #endif
1055             SetDisplayBrightness(UNDEFINED_BRIGHTNESS); // UNDEFINED_BRIGHTNESS means system default brightness
1056         }
1057         SetBrightnessWindow(INVALID_WINDOW_ID);
1058     } else {
1059         if (GetDisplayBrightness() != node->GetBrightness()) {
1060             WLOGI("adjust brightness with value: %{public}u", ToOverrideBrightness(node->GetBrightness()));
1061 #ifdef POWERMGR_DISPLAY_MANAGER_ENABLE
1062             DisplayPowerMgr::DisplayPowerMgrClient::GetInstance().OverrideBrightness(
1063                 ToOverrideBrightness(node->GetBrightness()));
1064 #endif
1065             SetDisplayBrightness(node->GetBrightness());
1066         }
1067         SetBrightnessWindow(node->GetWindowId());
1068     }
1069 }
1070 
AssignZOrder()1071 void WindowNodeContainer::AssignZOrder()
1072 {
1073     zOrder_ = 0;
1074     WindowNodeOperationFunc func = [this](sptr<WindowNode> node) {
1075         if (!node->leashWinSurfaceNode_ && !node->surfaceNode_ && !node->startingWinSurfaceNode_) {
1076             ++zOrder_;
1077             WLOGFE("Id: %{public}u has no surface nodes", node->GetWindowId());
1078             return false;
1079         }
1080         if (node->leashWinSurfaceNode_ != nullptr) {
1081             ++zOrder_;
1082             node->leashWinSurfaceNode_->SetPositionZ(zOrder_);
1083         }
1084 
1085         if (node->surfaceNode_ != nullptr) {
1086             ++zOrder_;
1087             node->surfaceNode_->SetPositionZ(zOrder_);
1088             node->zOrder_ = zOrder_;
1089         }
1090         // make sure starting window above app
1091         if (node->startingWinSurfaceNode_ != nullptr) {
1092             ++zOrder_;
1093             node->startingWinSurfaceNode_->SetPositionZ(zOrder_);
1094         }
1095         return false;
1096     };
1097     TraverseWindowTree(func, false);
1098     displayGroupController_->UpdateDisplayGroupWindowTree();
1099 }
1100 
SetFocusWindow(uint32_t windowId)1101 WMError WindowNodeContainer::SetFocusWindow(uint32_t windowId)
1102 {
1103     if (focusedWindow_ == windowId) {
1104         WLOGI("Focus window not change, id: %{public}u, %{public}d", windowId, focusedPid_);
1105         // StartingWindow can be focused and this pid is 0, then notify info in UpdateFocusStatus.
1106         // This info is invalid, so we must notify again when first frame callback.
1107         if (focusedPid_ == 0) {
1108             UpdateFocusStatus(windowId, true);
1109         }
1110         return WMError::WM_DO_NOTHING;
1111     }
1112     UpdateFocusStatus(focusedWindow_, false);
1113     focusedWindow_ = windowId;
1114     UpdateFocusStatus(focusedWindow_, true);
1115     return WMError::WM_OK;
1116 }
1117 
GetFocusWindow() const1118 uint32_t WindowNodeContainer::GetFocusWindow() const
1119 {
1120     return focusedWindow_;
1121 }
1122 
SetActiveWindow(uint32_t windowId, bool byRemoved)1123 WMError WindowNodeContainer::SetActiveWindow(uint32_t windowId, bool byRemoved)
1124 {
1125     if (activeWindow_ == windowId) {
1126         WLOGI("Active window not change, id: %{public}u, %{public}d", windowId, activePid_);
1127         if (activePid_ == 0) {
1128             UpdateActiveStatus(windowId, true);
1129         }
1130         return WMError::WM_DO_NOTHING;
1131     }
1132     UpdateActiveStatus(activeWindow_, false);
1133     activeWindow_ = windowId;
1134     UpdateActiveStatus(activeWindow_, true);
1135     UpdateBrightness(activeWindow_, byRemoved);
1136     return WMError::WM_OK;
1137 }
1138 
SetDisplayBrightness(float brightness)1139 void WindowNodeContainer::SetDisplayBrightness(float brightness)
1140 {
1141     displayBrightness_ = brightness;
1142 }
1143 
GetDisplayBrightness() const1144 float WindowNodeContainer::GetDisplayBrightness() const
1145 {
1146     return displayBrightness_;
1147 }
1148 
SetBrightnessWindow(uint32_t windowId)1149 void WindowNodeContainer::SetBrightnessWindow(uint32_t windowId)
1150 {
1151     brightnessWindow_ = windowId;
1152 }
1153 
GetBrightnessWindow() const1154 uint32_t WindowNodeContainer::GetBrightnessWindow() const
1155 {
1156     return brightnessWindow_;
1157 }
1158 
ToOverrideBrightness(float brightness)1159 uint32_t WindowNodeContainer::ToOverrideBrightness(float brightness)
1160 {
1161     return static_cast<uint32_t>(brightness * MAX_BRIGHTNESS);
1162 }
1163 
GetActiveWindow() const1164 uint32_t WindowNodeContainer::GetActiveWindow() const
1165 {
1166     return activeWindow_;
1167 }
1168 
GetLayoutPolicy() const1169 sptr<WindowLayoutPolicy> WindowNodeContainer::GetLayoutPolicy() const
1170 {
1171     return layoutPolicy_;
1172 }
1173 
GetAvoidController() const1174 sptr<AvoidAreaController> WindowNodeContainer::GetAvoidController() const
1175 {
1176     return avoidController_;
1177 }
1178 
GetDisplayGroupController() const1179 sptr<DisplayGroupController> WindowNodeContainer::GetDisplayGroupController() const
1180 {
1181     return displayGroupController_;
1182 }
1183 
GetRootNode(WindowRootNodeType type) const1184 sptr<WindowNode> WindowNodeContainer::GetRootNode(WindowRootNodeType type) const
1185 {
1186     if (type == WindowRootNodeType::ABOVE_WINDOW_NODE) {
1187         return aboveAppWindowNode_;
1188     } else if (type == WindowRootNodeType::APP_WINDOW_NODE) {
1189         return appWindowNode_;
1190     } else if (type == WindowRootNodeType::BELOW_WINDOW_NODE) {
1191         return belowAppWindowNode_;
1192     }
1193     return nullptr;
1194 }
1195 
HandleKeepScreenOn(const sptr<WindowNode>& node, bool requireLock)1196 void WindowNodeContainer::HandleKeepScreenOn(const sptr<WindowNode>& node, bool requireLock)
1197 {
1198 #ifdef POWER_MANAGER_ENABLE
1199     if (requireLock && node->keepScreenLock_ == nullptr) {
1200         // reset ipc identity
1201         std::string identity = IPCSkeleton::ResetCallingIdentity();
1202         node->keepScreenLock_ = PowerMgr::PowerMgrClient::GetInstance().CreateRunningLock(node->GetWindowName(),
1203             PowerMgr::RunningLockType::RUNNINGLOCK_SCREEN);
1204         // set ipc identity to raw
1205         IPCSkeleton::SetCallingIdentity(identity);
1206     }
1207     if (node->keepScreenLock_ == nullptr) {
1208         return;
1209     }
1210     WLOGI("keep screen on: [%{public}s, %{public}d]", node->GetWindowName().c_str(), requireLock);
1211     HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "container:HandleKeepScreenOn(%s, %d)",
1212         node->GetWindowName().c_str(), requireLock);
1213     ErrCode res;
1214     // reset ipc identity
1215     std::string identity = IPCSkeleton::ResetCallingIdentity();
1216     if (requireLock) {
1217         res = node->keepScreenLock_->Lock();
1218     } else {
1219         res = node->keepScreenLock_->UnLock();
1220     }
1221     // set ipc identity to raw
1222     IPCSkeleton::SetCallingIdentity(identity);
1223     if (res != ERR_OK) {
1224         WLOGFE("handle keep screen running lock failed: [operation: %{public}d, err: %{public}d]", requireLock, res);
1225     }
1226 #endif
1227 }
1228 
IsAboveSystemBarNode(sptr<WindowNode> node) const1229 bool WindowNodeContainer::IsAboveSystemBarNode(sptr<WindowNode> node) const
1230 {
1231     int32_t curPriority = zorderPolicy_->GetWindowPriority(node->GetWindowType());
1232     if ((curPriority > zorderPolicy_->GetWindowPriority(WindowType::WINDOW_TYPE_STATUS_BAR)) &&
1233         (curPriority > zorderPolicy_->GetWindowPriority(WindowType::WINDOW_TYPE_NAVIGATION_BAR))) {
1234         return true;
1235     }
1236     return false;
1237 }
1238 
IsSplitImmersiveNode(sptr<WindowNode> node) const1239 bool WindowNodeContainer::IsSplitImmersiveNode(sptr<WindowNode> node) const
1240 {
1241     auto type = node->GetWindowType();
1242     return node->IsSplitMode() || type == WindowType::WINDOW_TYPE_DOCK_SLICE;
1243 }
1244 
GetExpectImmersiveProperty(DisplayId id, sptr<WindowNode>& triggerWindow) const1245 std::unordered_map<WindowType, SystemBarProperty> WindowNodeContainer::GetExpectImmersiveProperty(DisplayId id,
1246     sptr<WindowNode>& triggerWindow) const
1247 {
1248     std::unordered_map<WindowType, SystemBarProperty> sysBarPropMap {
1249         { WindowType::WINDOW_TYPE_STATUS_BAR,     SystemBarProperty() },
1250         { WindowType::WINDOW_TYPE_NAVIGATION_BAR, SystemBarProperty() },
1251     };
1252 
1253     std::vector<sptr<WindowNode>> rootNodes = { aboveAppWindowNode_, appWindowNode_, belowAppWindowNode_ };
1254     if (layoutMode_ == WindowLayoutMode::TILE) {
1255         rootNodes = { aboveAppWindowNode_, belowAppWindowNode_ };
1256     }
1257 
1258     for (const auto& node : rootNodes) {
1259         for (auto iter = node->children_.rbegin(); iter < node->children_.rend(); ++iter) {
1260             auto& sysBarPropMapNode = (*iter)->GetSystemBarProperty();
1261             if (IsAboveSystemBarNode(*iter)) {
1262                 continue;
1263             }
1264             if (WindowHelper::IsFullScreenWindow((*iter)->GetWindowMode())
1265                 && (*iter)->GetWindowType() != WindowType::WINDOW_TYPE_PANEL) {
1266                 auto displayInfo = DisplayGroupInfo::GetInstance().GetDisplayInfo(id);
1267                 if (displayInfo && WmsUtils::IsExpectedRotateLandscapeWindow((*iter)->GetRequestedOrientation(),
1268                     displayInfo->GetDisplayOrientation(), (*iter)->GetWindowFlags())) {
1269                     WLOGFI("Horizontal window id: %{public}d make it immersive", (*iter)->GetWindowId());
1270                     for (auto it : sysBarPropMap) {
1271                         sysBarPropMap[it.first] = (sysBarPropMapNode.find(it.first))->second;
1272                         sysBarPropMap[it.first].enable_ = false;
1273                     }
1274                 } else {
1275                     WLOGFD("Top immersive window id: %{public}d. Use full immersive prop", (*iter)->GetWindowId());
1276                     for (auto it : sysBarPropMap) {
1277                         sysBarPropMap[it.first] = (sysBarPropMapNode.find(it.first))->second;
1278                     }
1279                     triggerWindow = (*iter);
1280                 }
1281                 return sysBarPropMap;
1282             } else if (IsSplitImmersiveNode(*iter)) {
1283                 WLOGFD("Top split window id: %{public}d. Use split immersive prop", (*iter)->GetWindowId());
1284                 for (auto it : sysBarPropMap) {
1285                     sysBarPropMap[it.first] = (sysBarPropMapNode.find(it.first))->second;
1286                     sysBarPropMap[it.first].enable_ = false;
1287                 }
1288                 return sysBarPropMap;
1289             }
1290         }
1291     }
1292 
1293     WLOGFD("No immersive window on top. Use default systembar Property");
1294     return sysBarPropMap;
1295 }
1296 
NotifyIfAvoidAreaChanged(const sptr<WindowNode>& node, const AvoidControlType avoidType) const1297 void WindowNodeContainer::NotifyIfAvoidAreaChanged(const sptr<WindowNode>& node,
1298     const AvoidControlType avoidType) const
1299 {
1300     auto checkFunc = [this](sptr<WindowNode> node) {
1301         return CheckWindowNodeWhetherInWindowTree(node);
1302     };
1303     avoidController_->ProcessWindowChange(node, avoidType, checkFunc);
1304     if (WindowHelper::IsSystemBarWindow(node->GetWindowType())) {
1305         NotifyIfSystemBarRegionChanged(node->GetDisplayId());
1306     } else {
1307         NotifyIfSystemBarTintChanged(node->GetDisplayId());
1308     }
1309 
1310     NotifyIfKeyboardRegionChanged(node, avoidType);
1311 }
1312 
BeforeProcessWindowAvoidAreaChangeWhenDisplayChange() const1313 void WindowNodeContainer::BeforeProcessWindowAvoidAreaChangeWhenDisplayChange() const
1314 {
1315     avoidController_->SetFlagForProcessWindowChange(true);
1316 }
1317 
ProcessWindowAvoidAreaChangeWhenDisplayChange() const1318 void WindowNodeContainer::ProcessWindowAvoidAreaChangeWhenDisplayChange() const
1319 {
1320     avoidController_->SetFlagForProcessWindowChange(false);
1321     auto checkFunc = [this](sptr<WindowNode> node) {
1322         return CheckWindowNodeWhetherInWindowTree(node);
1323     };
1324     WindowNodeOperationFunc func = [avoidController = avoidController_, &checkFunc](sptr<WindowNode> node) {
1325         avoidController->ProcessWindowChange(node, AvoidControlType::AVOID_NODE_UPDATE, checkFunc);
1326         return false;
1327     };
1328     TraverseWindowTree(func, true);
1329 }
1330 
NotifyIfSystemBarTintChanged(DisplayId displayId) const1331 void WindowNodeContainer::NotifyIfSystemBarTintChanged(DisplayId displayId) const
1332 {
1333     HITRACE_METER(HITRACE_TAG_WINDOW_MANAGER);
1334     sptr<WindowNode> triggerWindow = nullptr;
1335     auto expectSystemBarProp = GetExpectImmersiveProperty(displayId, triggerWindow);
1336     JudgeToReportSystemBarInfo(triggerWindow, expectSystemBarProp);
1337     SystemBarRegionTints tints;
1338     SysBarTintMap& sysBarTintMap = displayGroupController_->sysBarTintMaps_[displayId];
1339     for (auto it : sysBarTintMap) {
1340         auto expectProp = expectSystemBarProp.find(it.first)->second;
1341         if (it.second.prop_ == expectProp) {
1342             continue;
1343         }
1344         WLOGFD("System bar prop update, Type: %{public}d, Visible: %{public}d, Color: %{public}x | %{public}x",
1345             static_cast<int32_t>(it.first), expectProp.enable_, expectProp.backgroundColor_, expectProp.contentColor_);
1346         sysBarTintMap[it.first].prop_ = expectProp;
1347         sysBarTintMap[it.first].type_ = it.first;
1348         tints.emplace_back(sysBarTintMap[it.first]);
1349     }
1350     WindowManagerAgentController::GetInstance().UpdateSystemBarRegionTints(displayId, tints);
1351 }
1352 
JudgeToReportSystemBarInfo(const sptr<WindowNode> window, const std::unordered_map<WindowType, SystemBarProperty>& systemBarPropInfo) const1353 void WindowNodeContainer::JudgeToReportSystemBarInfo(const sptr<WindowNode> window,
1354     const std::unordered_map<WindowType, SystemBarProperty>& systemBarPropInfo) const
1355 {
1356     if (window == nullptr || !WindowHelper::IsMainWindow(window->GetWindowType())) {
1357         WLOGFD("No need to report");
1358         return;
1359     }
1360 
1361     // 2 means the must size of systemBarPropInfo.
1362     if (systemBarPropInfo.size() != 2) {
1363         return;
1364     }
1365 
1366     auto bundleName = window->abilityInfo_.bundleName_;
1367     auto abilityName = window->abilityInfo_.abilityName_;
1368     auto navigationItor = systemBarPropInfo.find(WindowType::WINDOW_TYPE_NAVIGATION_BAR);
1369     if (navigationItor != systemBarPropInfo.end() && !navigationItor->second.enable_) {
1370         WindowInfoReporter::GetInstance().InsertNavigationBarReportInfo(bundleName, abilityName);
1371         WLOGFD("the navigation bar is disabled by window. windowId:[%{public}u]", window->GetWindowId());
1372     }
1373 }
1374 
NotifyIfSystemBarRegionChanged(DisplayId displayId) const1375 void WindowNodeContainer::NotifyIfSystemBarRegionChanged(DisplayId displayId) const
1376 {
1377     HITRACE_METER(HITRACE_TAG_WINDOW_MANAGER);
1378     SystemBarRegionTints tints;
1379     SysBarTintMap& sysBarTintMap = displayGroupController_->sysBarTintMaps_[displayId];
1380     SysBarNodeMap& sysBarNodeMap = displayGroupController_->sysBarNodeMaps_[displayId];
1381     for (auto it : sysBarTintMap) { // split screen mode not support yet
1382         auto sysNode = sysBarNodeMap[it.first];
1383         if (sysNode == nullptr || it.second.region_ == sysNode->GetWindowRect()) {
1384             continue;
1385         }
1386         const Rect& newRegion = sysNode->GetWindowRect();
1387         sysBarTintMap[it.first].region_ = newRegion;
1388         sysBarTintMap[it.first].type_ = it.first;
1389         tints.emplace_back(sysBarTintMap[it.first]);
1390         WLOGD("system bar region update, type: %{public}d" \
1391             "region: [%{public}d, %{public}d, %{public}d, %{public}d]",
1392             static_cast<int32_t>(it.first), newRegion.posX_, newRegion.posY_, newRegion.width_, newRegion.height_);
1393     }
1394     WindowManagerAgentController::GetInstance().UpdateSystemBarRegionTints(displayId, tints);
1395 }
1396 
NotifyIfKeyboardRegionChanged(const sptr<WindowNode>& node, const AvoidControlType avoidType) const1397 void WindowNodeContainer::NotifyIfKeyboardRegionChanged(const sptr<WindowNode>& node,
1398     const AvoidControlType avoidType) const
1399 {
1400     WindowGravity windowGravity;
1401     uint32_t percent;
1402     node->GetWindowGravity(windowGravity, percent);
1403     if (node->GetWindowType() != WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT ||
1404         windowGravity == WindowGravity::WINDOW_GRAVITY_FLOAT) {
1405         WLOGFD("windowType: %{public}u", node->GetWindowType());
1406         return;
1407     }
1408 
1409     auto callingWindow = FindWindowNodeById(node->GetCallingWindow());
1410     if (callingWindow == nullptr) {
1411         WLOGD("callingWindow: %{public}u does not be set", node->GetCallingWindow());
1412         callingWindow = FindWindowNodeById(GetFocusWindow());
1413     }
1414     if (callingWindow == nullptr || callingWindow->GetWindowToken() == nullptr) {
1415         WLOGE("does not have correct callingWindow for input method window");
1416         return;
1417     }
1418     const WindowMode callingWindowMode = callingWindow->GetWindowMode();
1419     if (callingWindowMode == WindowMode::WINDOW_MODE_FULLSCREEN ||
1420         callingWindowMode == WindowMode::WINDOW_MODE_SPLIT_PRIMARY ||
1421         callingWindowMode == WindowMode::WINDOW_MODE_SPLIT_SECONDARY) {
1422         const Rect keyRect = node->GetWindowRect();
1423         const Rect callingRect = callingWindow->GetWindowRect();
1424         if (WindowHelper::IsEmptyRect(WindowHelper::GetOverlap(callingRect, keyRect, 0, 0))) {
1425             WLOGFD("no overlap between two windows");
1426             return;
1427         }
1428         Rect overlapRect = { 0, 0, 0, 0 };
1429         if (avoidType == AvoidControlType::AVOID_NODE_ADD || avoidType == AvoidControlType::AVOID_NODE_UPDATE) {
1430             overlapRect = WindowHelper::GetOverlap(keyRect, callingRect, callingRect.posX_, callingRect.posY_);
1431         }
1432         double textFieldPositionY = 0.0;
1433         double textFieldHeight = 0.0;
1434         if (node->GetWindowProperty() != nullptr) {
1435             textFieldPositionY = node->GetWindowProperty()->GetTextFieldPositionY();
1436             textFieldHeight = node->GetWindowProperty()->GetTextFieldHeight();
1437         }
1438         sptr<OccupiedAreaChangeInfo> info = new OccupiedAreaChangeInfo(OccupiedAreaType::TYPE_INPUT,
1439             overlapRect, textFieldPositionY, textFieldHeight);
1440         if (isAnimateTransactionEnabled_) {
1441             auto syncTransactionController = RSSyncTransactionController::GetInstance();
1442             if (syncTransactionController) {
1443                 callingWindow->GetWindowToken()->UpdateOccupiedAreaChangeInfo(info,
1444                     syncTransactionController->GetRSTransaction());
1445             }
1446         } else {
1447             callingWindow->GetWindowToken()->UpdateOccupiedAreaChangeInfo(info);
1448         }
1449 
1450         WLOGD("keyboard size change callingWindow: [%{public}s, %{public}u], "
1451             "overlap rect: [%{public}d, %{public}d, %{public}u, %{public}u]",
1452             callingWindow->GetWindowName().c_str(), callingWindow->GetWindowId(),
1453             overlapRect.posX_, overlapRect.posY_, overlapRect.width_, overlapRect.height_);
1454         return;
1455     }
1456     WLOGFE("does not have correct callingWindowMode for input method window");
1457 }
1458 
NotifySystemBarTints(std::vector<DisplayId> displayIdVec)1459 void WindowNodeContainer::NotifySystemBarTints(std::vector<DisplayId> displayIdVec)
1460 {
1461     if (displayIdVec.size() != displayGroupController_->sysBarTintMaps_.size()) {
1462         WLOGE("[Immersive] the number of display is error");
1463     }
1464 
1465     for (auto displayId : displayIdVec) {
1466         SystemBarRegionTints tints;
1467         SysBarTintMap& sysBarTintMap = displayGroupController_->sysBarTintMaps_[displayId];
1468         for (auto it : sysBarTintMap) {
1469             WLOGI("[Immersive] systembar tints, T: %{public}d, " \
1470                 "V: %{public}d, C: %{public}x | %{public}x, " \
1471                 "R: [%{public}d, %{public}d, %{public}d, %{public}d]",
1472                 static_cast<int32_t>(it.first),
1473                 sysBarTintMap[it.first].prop_.enable_,
1474                 sysBarTintMap[it.first].prop_.backgroundColor_, sysBarTintMap[it.first].prop_.contentColor_,
1475                 sysBarTintMap[it.first].region_.posX_, sysBarTintMap[it.first].region_.posY_,
1476                 sysBarTintMap[it.first].region_.width_, sysBarTintMap[it.first].region_.height_);
1477             tints.push_back(sysBarTintMap[it.first]);
1478         }
1479         WindowManagerAgentController::GetInstance().UpdateSystemBarRegionTints(displayId, tints);
1480     }
1481 }
1482 
NotifyDockWindowStateChanged(sptr<WindowNode>& node, bool isEnable)1483 void WindowNodeContainer::NotifyDockWindowStateChanged(sptr<WindowNode>& node, bool isEnable)
1484 {
1485     HITRACE_METER(HITRACE_TAG_WINDOW_MANAGER);
1486     WLOGFD("[Immersive] begin isEnable: %{public}d", isEnable);
1487     if (isEnable) {
1488         for (auto& windowNode : appWindowNode_->children_) {
1489             if (windowNode->GetWindowId() == node->GetWindowId()) {
1490                 continue;
1491             }
1492             if (!WindowHelper::IsFloatingWindow(windowNode->GetWindowMode())) {
1493                 return;
1494             }
1495         }
1496     }
1497     SystemBarProperty prop;
1498     prop.enable_ = isEnable;
1499     SystemBarRegionTint tint;
1500     tint.type_ = WindowType::WINDOW_TYPE_LAUNCHER_DOCK;
1501     tint.prop_ = prop;
1502     SystemBarRegionTints tints;
1503     tints.push_back(tint);
1504     WindowManagerAgentController::GetInstance().UpdateSystemBarRegionTints(node->GetDisplayId(), tints);
1505 }
1506 
NotifyDockWindowStateChanged(DisplayId displayId)1507 void WindowNodeContainer::NotifyDockWindowStateChanged(DisplayId displayId)
1508 {
1509     HITRACE_METER(HITRACE_TAG_WINDOW_MANAGER);
1510     bool isEnable = true;
1511     for (auto& windowNode : appWindowNode_->children_) {
1512         if (WindowHelper::IsSplitWindowMode(windowNode->GetWindowMode()) ||
1513             WindowHelper::IsFullScreenWindow(windowNode->GetWindowMode())) {
1514             isEnable = false;
1515             break;
1516         }
1517     }
1518     WLOGFD("[Immersive] display %{public}" PRIu64" begin isEnable: %{public}d", displayId, isEnable);
1519     SystemBarProperty prop;
1520     prop.enable_ = isEnable;
1521     SystemBarRegionTint tint;
1522     tint.type_ = WindowType::WINDOW_TYPE_LAUNCHER_DOCK;
1523     tint.prop_ = prop;
1524     SystemBarRegionTints tints;
1525     tints.push_back(tint);
1526     WindowManagerAgentController::GetInstance().UpdateSystemBarRegionTints(displayId, tints);
1527 }
1528 
UpdateAvoidAreaListener(sptr<WindowNode>& windowNode, bool haveAvoidAreaListener)1529 void WindowNodeContainer::UpdateAvoidAreaListener(sptr<WindowNode>& windowNode, bool haveAvoidAreaListener)
1530 {
1531     avoidController_->UpdateAvoidAreaListener(windowNode, haveAvoidAreaListener);
1532 }
1533 
IsTopWindow(uint32_t windowId, sptr<WindowNode>& rootNode) const1534 bool WindowNodeContainer::IsTopWindow(uint32_t windowId, sptr<WindowNode>& rootNode) const
1535 {
1536     if (rootNode->children_.empty()) {
1537         WLOGFE("root does not have any node");
1538         return false;
1539     }
1540     auto node = *(rootNode->children_.rbegin());
1541     if (node == nullptr) {
1542         WLOGFE("window tree does not have any node");
1543         return false;
1544     }
1545 
1546     for (auto iter = node->children_.rbegin(); iter < node->children_.rend(); iter++) {
1547         if ((*iter)->priority_ > 0) {
1548             return (*iter)->GetWindowId() == windowId;
1549         } else {
1550             break;
1551         }
1552     }
1553     return node->GetWindowId() == windowId;
1554 }
1555 
RaiseOrderedWindowToTop(std::vector<sptr<WindowNode>>& orderedNodes, std::vector<sptr<WindowNode>>& windowNodes)1556 void WindowNodeContainer::RaiseOrderedWindowToTop(std::vector<sptr<WindowNode>>& orderedNodes,
1557     std::vector<sptr<WindowNode>>& windowNodes)
1558 {
1559     for (auto iter = appWindowNode_->children_.begin(); iter != appWindowNode_->children_.end();) {
1560         uint32_t wid = (*iter)->GetWindowId();
1561         auto orderedIter = std::find_if(orderedNodes.begin(), orderedNodes.end(),
1562             [wid] (sptr<WindowNode> orderedNode) { return orderedNode->GetWindowId() == wid; });
1563         if (orderedIter != orderedNodes.end()) {
1564             iter = windowNodes.erase(iter);
1565         } else {
1566             iter++;
1567         }
1568     }
1569     for (auto iter = orderedNodes.begin(); iter != orderedNodes.end(); iter++) {
1570         UpdateWindowTree(*iter);
1571     }
1572     return;
1573 }
1574 
RaiseWindowToTop(uint32_t windowId, std::vector<sptr<WindowNode>>& windowNodes)1575 void WindowNodeContainer::RaiseWindowToTop(uint32_t windowId, std::vector<sptr<WindowNode>>& windowNodes)
1576 {
1577     if (windowNodes.empty()) {
1578         WLOGFE("windowNodes is empty!");
1579         return;
1580     }
1581     auto iter = std::find_if(windowNodes.begin(), windowNodes.end(),
1582                              [windowId](sptr<WindowNode> node) {
1583                                  return node->GetWindowId() == windowId;
1584                              });
1585     // raise app node window to top
1586     if (iter != windowNodes.end()) {
1587         sptr<WindowNode> node = *iter;
1588         windowNodes.erase(iter);
1589         UpdateWindowTree(node);
1590         WLOGD("raise window to top %{public}u", node->GetWindowId());
1591     }
1592 }
1593 
TraverseContainer(std::vector<sptr<WindowNode>>& windowNodes) const1594 void WindowNodeContainer::TraverseContainer(std::vector<sptr<WindowNode>>& windowNodes) const
1595 {
1596     for (auto& node : belowAppWindowNode_->children_) {
1597         TraverseWindowNode(node, windowNodes);
1598     }
1599     for (auto& node : appWindowNode_->children_) {
1600         TraverseWindowNode(node, windowNodes);
1601     }
1602     for (auto& node : aboveAppWindowNode_->children_) {
1603         TraverseWindowNode(node, windowNodes);
1604     }
1605     std::reverse(windowNodes.begin(), windowNodes.end());
1606 }
1607 
TraverseWindowNode(sptr<WindowNode>& node, std::vector<sptr<WindowNode>>& windowNodes) const1608 void WindowNodeContainer::TraverseWindowNode(sptr<WindowNode>& node, std::vector<sptr<WindowNode>>& windowNodes) const
1609 {
1610     if (node == nullptr) {
1611         return;
1612     }
1613     auto iter = node->children_.begin();
1614     for (; iter < node->children_.end(); ++iter) {
1615         if ((*iter)->priority_ < 0) {
1616             windowNodes.emplace_back(*iter);
1617         } else {
1618             break;
1619         }
1620     }
1621     windowNodes.emplace_back(node);
1622     for (; iter < node->children_.end(); ++iter) {
1623         windowNodes.emplace_back(*iter);
1624     }
1625 }
1626 
GetAvoidAreaByType(const sptr<WindowNode>& node, AvoidAreaType avoidAreaType) const1627 AvoidArea WindowNodeContainer::GetAvoidAreaByType(const sptr<WindowNode>& node, AvoidAreaType avoidAreaType) const
1628 {
1629     if (CheckWindowNodeWhetherInWindowTree(node)) {
1630         return avoidController_->GetAvoidAreaByType(node, avoidAreaType);
1631     }
1632     return {};
1633 }
1634 
CheckWindowNodeWhetherInWindowTree(const sptr<WindowNode>& node) const1635 bool WindowNodeContainer::CheckWindowNodeWhetherInWindowTree(const sptr<WindowNode>& node) const
1636 {
1637     bool isInWindowTree = false;
1638     WindowNodeOperationFunc func = [&node, &isInWindowTree](sptr<WindowNode> windowNode) {
1639         if (node->GetWindowId() == windowNode->GetWindowId()) {
1640             isInWindowTree = true;
1641             return true;
1642         }
1643         return false;
1644     };
1645     TraverseWindowTree(func, true);
1646     return isInWindowTree;
1647 }
1648 
DumpScreenWindowTreeByWinId(uint32_t winid)1649 void WindowNodeContainer::DumpScreenWindowTreeByWinId(uint32_t winid)
1650 {
1651     WLOGFD("------ dump window info begin -------");
1652     WLOGFD("WindowName WinId Type Mode ZOrd [   x    y    w    h]");
1653     uint32_t zOrder = zOrder_;
1654     WindowNodeOperationFunc func = [&zOrder, &winid](sptr<WindowNode> node) {
1655         Rect rect = node->GetWindowRect();
1656         uint32_t windowId = node->GetWindowId();
1657         const std::string& windowName = node->GetWindowName().size() < WINDOW_NAME_MAX_LENGTH ?
1658             node->GetWindowName() : node->GetWindowName().substr(0, WINDOW_NAME_MAX_LENGTH);
1659         if (winid == windowId) {
1660             WLOGD("DumpScreenWindowTree: %{public}10s  %{public}5u %{public}4u %{public}4u "
1661                 "%{public}4u [%{public}4d %{public}4d %{public}4u %{public}4u]",
1662                 windowName.c_str(), node->GetWindowId(), node->GetWindowType(), node->GetWindowMode(),
1663                 --zOrder, rect.posX_, rect.posY_, rect.width_, rect.height_);
1664         } else {
1665             WLOGD("DumpScreenWindowTree: %{public}10s  %{public}5u %{public}4u %{public}4u "
1666                 "%{public}4u [%{public}4d %{public}4d %{public}4u %{public}4u]",
1667                 windowName.c_str(), node->GetWindowId(), node->GetWindowType(), node->GetWindowMode(),
1668                 --zOrder, rect.posX_, rect.posY_, rect.width_, rect.height_);
1669         }
1670         return false;
1671     };
1672     TraverseWindowTree(func, true);
1673     WLOGFD("------ dump window info end -------");
1674 }
1675 
DumpScreenWindowTree()1676 void WindowNodeContainer::DumpScreenWindowTree()
1677 {
1678     WLOGI("------ dump window info begin -------");
1679     WLOGI("WindowName DisplayId WinId Type Mode Flag ZOrd Orientation firstFrameCallback [   x    y    w    h]");
1680     uint32_t zOrder = zOrder_;
1681     WindowNodeOperationFunc func = [&zOrder](sptr<WindowNode> node) {
1682         Rect rect = node->GetWindowRect();
1683         const std::string& windowName = node->GetWindowName().size() < WINDOW_NAME_MAX_LENGTH ?
1684             node->GetWindowName() : node->GetWindowName().substr(0, WINDOW_NAME_MAX_LENGTH);
1685         WLOGI("DumpScreenWindowTree: %{public}10s %{public}9" PRIu64" %{public}5u %{public}4u %{public}4u %{public}4u "
1686             "%{public}4u %{public}11u %{public}12d [%{public}4d %{public}4d %{public}4u %{public}4u]",
1687             windowName.c_str(), node->GetDisplayId(), node->GetWindowId(), node->GetWindowType(), node->GetWindowMode(),
1688             node->GetWindowFlags(), --zOrder, static_cast<uint32_t>(node->GetRequestedOrientation()),
1689             node->firstFrameAvailable_, rect.posX_, rect.posY_, rect.width_, rect.height_);
1690         return false;
1691     };
1692     TraverseWindowTree(func, true);
1693     WLOGI("------ dump window info end -------");
1694 }
1695 
IsVerticalDisplay(DisplayId displayId) const1696 bool WindowNodeContainer::IsVerticalDisplay(DisplayId displayId) const
1697 {
1698     return DisplayGroupInfo::GetInstance().GetDisplayRect(displayId).width_ <
1699         DisplayGroupInfo::GetInstance().GetDisplayRect(displayId).height_;
1700 }
1701 
ProcessWindowStateChange(WindowState state, WindowStateChangeReason reason)1702 void WindowNodeContainer::ProcessWindowStateChange(WindowState state, WindowStateChangeReason reason)
1703 {
1704     switch (reason) {
1705         case WindowStateChangeReason::KEYGUARD: {
1706             int32_t topPriority = zorderPolicy_->GetWindowPriority(WindowType::WINDOW_TYPE_KEYGUARD);
1707             TraverseAndUpdateWindowState(state, topPriority);
1708             break;
1709         }
1710         default:
1711             return;
1712     }
1713 }
1714 
TraverseAndUpdateWindowState(WindowState state, int32_t topPriority)1715 void WindowNodeContainer::TraverseAndUpdateWindowState(WindowState state, int32_t topPriority)
1716 {
1717     std::vector<sptr<WindowNode>> rootNodes = { belowAppWindowNode_, appWindowNode_, aboveAppWindowNode_ };
1718     for (auto& node : rootNodes) {
1719         UpdateWindowState(node, topPriority, state);
1720     }
1721 }
1722 
UpdateWindowState(sptr<WindowNode> node, int32_t topPriority, WindowState state)1723 void WindowNodeContainer::UpdateWindowState(sptr<WindowNode> node, int32_t topPriority, WindowState state)
1724 {
1725     if (node == nullptr) {
1726         return;
1727     }
1728     if (node->parent_ != nullptr && node->currentVisibility_) {
1729         if (node->priority_ < topPriority && !WindowHelper::IsShowWhenLocked(node->GetWindowFlags()) &&
1730             !WindowHelper::IsShowWhenLocked(node->parent_->GetWindowFlags())) {
1731             if (node->GetWindowToken()) {
1732                 node->GetWindowToken()->UpdateWindowState(state);
1733             }
1734             HandleKeepScreenOn(node, state);
1735         }
1736     }
1737     for (auto& childNode : node->children_) {
1738         UpdateWindowState(childNode, topPriority, state);
1739     }
1740 }
1741 
HandleKeepScreenOn(const sptr<WindowNode>& node, WindowState state)1742 void WindowNodeContainer::HandleKeepScreenOn(const sptr<WindowNode>& node, WindowState state)
1743 {
1744     if (node == nullptr) {
1745         WLOGFE("window is invalid");
1746         return;
1747     }
1748     if (state == WindowState::STATE_FROZEN) {
1749         HandleKeepScreenOn(node, false);
1750     } else if (state == WindowState::STATE_UNFROZEN) {
1751         HandleKeepScreenOn(node, node->IsKeepScreenOn());
1752     } else {
1753         // do nothing
1754     }
1755 }
1756 
FindDividerNode() const1757 sptr<WindowNode> WindowNodeContainer::FindDividerNode() const
1758 {
1759     for (auto iter = appWindowNode_->children_.begin(); iter != appWindowNode_->children_.end(); iter++) {
1760         if ((*iter)->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) {
1761             return *iter;
1762         }
1763     }
1764     return nullptr;
1765 }
1766 
RaiseSplitRelatedWindowToTop(sptr<WindowNode>& node)1767 void WindowNodeContainer::RaiseSplitRelatedWindowToTop(sptr<WindowNode>& node)
1768 {
1769     if (node == nullptr) {
1770         return;
1771     }
1772     auto windowPair = displayGroupController_->GetWindowPairByDisplayId(node->GetDisplayId());
1773     if (windowPair == nullptr) {
1774         WLOGFE("Window pair is nullptr");
1775         return;
1776     }
1777     std::vector<sptr<WindowNode>> orderedPair = windowPair->GetOrderedPair(node);
1778     RaiseOrderedWindowToTop(orderedPair, appWindowNode_->children_);
1779     AssignZOrder();
1780     return;
1781 }
1782 
RaiseZOrderForAppWindow(sptr<WindowNode>& node, sptr<WindowNode>& parentNode)1783 WMError WindowNodeContainer::RaiseZOrderForAppWindow(sptr<WindowNode>& node, sptr<WindowNode>& parentNode)
1784 {
1785     if (node == nullptr) {
1786         return WMError::WM_ERROR_NULLPTR;
1787     }
1788     if (IsTopWindow(node->GetWindowId(), appWindowNode_) || IsTopWindow(node->GetWindowId(), aboveAppWindowNode_)) {
1789         WLOGE("Window %{public}u is already at top", node->GetWindowId());
1790         return WMError::WM_ERROR_INVALID_TYPE;
1791     }
1792 
1793     if (WindowHelper::IsSubWindow(node->GetWindowType()) ||
1794         (node->GetWindowType() == WindowType::WINDOW_TYPE_DIALOG)) {
1795         if (parentNode == nullptr) {
1796             WLOGFE("window type is invalid");
1797             return WMError::WM_ERROR_NULLPTR;
1798         }
1799         RaiseWindowToTop(node->GetWindowId(), parentNode->children_); // raise itself
1800         if (parentNode->IsSplitMode()) {
1801             RaiseSplitRelatedWindowToTop(parentNode);
1802         } else if (parentNode->parent_ != nullptr) {
1803             RaiseWindowToTop(parentNode->GetWindowId(), parentNode->parent_->children_); // raise parent window
1804         }
1805     } else if (WindowHelper::IsMainWindow(node->GetWindowType())) {
1806         if (node->IsSplitMode()) {
1807             RaiseSplitRelatedWindowToTop(node);
1808         } else {
1809             // remote animation continuous start and exit allow parent is nullptr
1810             if (node->parent_ == nullptr) {
1811                 WLOGFW("node parent is nullptr");
1812                 return WMError::WM_OK;
1813             }
1814             RaiseWindowToTop(node->GetWindowId(), node->parent_->children_);
1815         }
1816     } else {
1817         // do nothing
1818     }
1819 
1820     AssignZOrder();
1821     WLOGI("Raise app window zorder");
1822     DumpScreenWindowTreeByWinId(node->GetWindowId());
1823     return WMError::WM_OK;
1824 }
1825 
GetNextFocusableWindow(uint32_t windowId) const1826 sptr<WindowNode> WindowNodeContainer::GetNextFocusableWindow(uint32_t windowId) const
1827 {
1828     sptr<WindowNode> nextFocusableWindow;
1829     bool previousFocusedWindowFound = false;
1830     WindowNodeOperationFunc func = [windowId, &nextFocusableWindow, &previousFocusedWindowFound](
1831         sptr<WindowNode> node) {
1832         if (previousFocusedWindowFound && node->GetWindowProperty()->GetFocusable() && node->currentVisibility_) {
1833             nextFocusableWindow = node;
1834             return true;
1835         }
1836         if (node->GetWindowId() == windowId) {
1837             previousFocusedWindowFound = true;
1838         }
1839         return false;
1840     };
1841     TraverseWindowTree(func, true);
1842     return nextFocusableWindow;
1843 }
1844 
GetNextRotatableWindow(uint32_t windowId) const1845 sptr<WindowNode> WindowNodeContainer::GetNextRotatableWindow(uint32_t windowId) const
1846 {
1847     sptr<WindowNode> nextRotatableWindow;
1848     WindowNodeOperationFunc func = [windowId, &nextRotatableWindow](
1849         sptr<WindowNode> node) {
1850         if (windowId != node->GetWindowId() &&
1851             WindowHelper::IsRotatableWindow(node->GetWindowType(), node->GetWindowMode())) {
1852             nextRotatableWindow = node;
1853             return true;
1854         }
1855         return false;
1856     };
1857     TraverseWindowTree(func, true);
1858     return nextRotatableWindow;
1859 }
1860 
GetNextActiveWindow(uint32_t windowId) const1861 sptr<WindowNode> WindowNodeContainer::GetNextActiveWindow(uint32_t windowId) const
1862 {
1863     auto currentNode = FindWindowNodeById(windowId);
1864     if (currentNode == nullptr) {
1865         WLOGFE("cannot find window id: %{public}u by tree", windowId);
1866         return nullptr;
1867     }
1868     WLOGFD("current window: [%{public}u, %{public}u]", windowId, static_cast<uint32_t>(currentNode->GetWindowType()));
1869     if (WindowHelper::IsSystemWindow(currentNode->GetWindowType())) {
1870         for (auto& node : appWindowNode_->children_) {
1871             if (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) {
1872                 continue;
1873             }
1874             return node;
1875         }
1876         for (auto& node : belowAppWindowNode_->children_) {
1877             if (node->GetWindowType() == WindowType::WINDOW_TYPE_DESKTOP) {
1878                 return node;
1879             }
1880         }
1881     } else if (WindowHelper::IsAppWindow(currentNode->GetWindowType())) {
1882         std::vector<sptr<WindowNode>> windowNodes;
1883         TraverseContainer(windowNodes);
1884         auto iter = std::find_if(windowNodes.begin(), windowNodes.end(), [windowId](sptr<WindowNode>& node) {
1885             return node->GetWindowId() == windowId;
1886             });
1887         if (iter == windowNodes.end()) {
1888             WLOGFE("could not find this window");
1889             return nullptr;
1890         }
1891         int index = std::distance(windowNodes.begin(), iter);
1892         for (size_t i = static_cast<size_t>(index) + 1; i < windowNodes.size(); i++) {
1893             if (windowNodes[i]->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE
1894                 || !windowNodes[i]->currentVisibility_) {
1895                 continue;
1896             }
1897             return windowNodes[i];
1898         }
1899     } else {
1900         // do nothing
1901     }
1902     WLOGFE("could not get next active window");
1903     return nullptr;
1904 }
1905 
IsForbidDockSliceMove(DisplayId displayId) const1906 bool WindowNodeContainer::IsForbidDockSliceMove(DisplayId displayId) const
1907 {
1908     auto windowPair = displayGroupController_->GetWindowPairByDisplayId(displayId);
1909     if (windowPair == nullptr) {
1910         WLOGFE("window pair is nullptr");
1911         return true;
1912     }
1913     if (windowPair->IsForbidDockSliceMove()) {
1914         return true;
1915     }
1916     return false;
1917 }
1918 
IsDockSliceInExitSplitModeArea(DisplayId displayId) const1919 bool WindowNodeContainer::IsDockSliceInExitSplitModeArea(DisplayId displayId) const
1920 {
1921     auto windowPair = displayGroupController_->GetWindowPairByDisplayId(displayId);
1922     if (windowPair == nullptr) {
1923         WLOGFE("window pair is nullptr");
1924         return false;
1925     }
1926     std::vector<int32_t> exitSplitPoints = windowPair->GetExitSplitPoints();
1927     if (exitSplitPoints.size() != EXIT_SPLIT_POINTS_NUMBER) {
1928         return false;
1929     }
1930     return windowPair->IsDockSliceInExitSplitModeArea(exitSplitPoints);
1931 }
1932 
ExitSplitMode(DisplayId displayId)1933 void WindowNodeContainer::ExitSplitMode(DisplayId displayId)
1934 {
1935     auto windowPair = displayGroupController_->GetWindowPairByDisplayId(displayId);
1936     if (windowPair == nullptr) {
1937         WLOGFE("window pair is nullptr");
1938         return;
1939     }
1940     windowPair->ExitSplitMode();
1941 }
1942 
MinimizeAllAppWindows(DisplayId displayId)1943 void WindowNodeContainer::MinimizeAllAppWindows(DisplayId displayId)
1944 {
1945     WMError ret = MinimizeAppNodeExceptOptions(MinimizeReason::MINIMIZE_ALL);
1946     SwitchLayoutPolicy(WindowLayoutMode::CASCADE, displayId);
1947     if (ret != WMError::WM_OK) {
1948         WLOGFE("Minimize all app window failed");
1949     }
1950     return;
1951 }
1952 
GetDeskTopWindow()1953 sptr<WindowNode> WindowNodeContainer::GetDeskTopWindow()
1954 {
1955     sptr<WindowNode> deskTop;
1956     WindowNodeOperationFunc findDeskTopFunc = [this, &deskTop](sptr<WindowNode> node) {
1957         if (node->GetWindowProperty()->GetWindowType() == WindowType::WINDOW_TYPE_DESKTOP) {
1958             deskTop = node;
1959             return true;
1960         }
1961         return false;
1962     };
1963     TraverseWindowTree(findDeskTopFunc, false);
1964     return deskTop;
1965 }
1966 
HasPrivateWindow()1967 bool WindowNodeContainer::HasPrivateWindow()
1968 {
1969     std::vector<sptr<WindowNode>> windowNodes;
1970     TraverseContainer(windowNodes);
1971     for (const auto& node : windowNodes) {
1972         if (node && node->GetVisibilityState() < WINDOW_VISIBILITY_STATE_TOTALLY_OCCUSION &&
1973             node->GetWindowProperty()->GetPrivacyMode()) {
1974             WLOGI("window name %{public}s", node->GetWindowName().c_str());
1975             return true;
1976         }
1977     }
1978     return false;
1979 }
1980 
HasMainFullScreenWindowShown()1981 bool WindowNodeContainer::HasMainFullScreenWindowShown()
1982 {
1983     std::vector<sptr<WindowNode>> windowNodes;
1984     for (auto& node : appWindowNode_->children_) {
1985         TraverseWindowNode(node, windowNodes);
1986     }
1987     for (const auto& node : windowNodes) {
1988         if (node->currentVisibility_ &&
1989             WindowHelper::IsMainFullScreenWindow(node->GetWindowType(), node->GetWindowMode())) {
1990             return true;
1991         }
1992     }
1993     return false;
1994 }
1995 
MinimizeOldestAppWindow()1996 void WindowNodeContainer::MinimizeOldestAppWindow()
1997 {
1998     for (auto& appNode : appWindowNode_->children_) {
1999         if (appNode->GetWindowType() == WindowType::WINDOW_TYPE_APP_MAIN_WINDOW) {
2000             MinimizeApp::AddNeedMinimizeApp(appNode, MinimizeReason::MAX_APP_COUNT);
2001             return;
2002         }
2003     }
2004     for (auto& appNode : aboveAppWindowNode_->children_) {
2005         if (appNode->GetWindowType() == WindowType::WINDOW_TYPE_APP_MAIN_WINDOW) {
2006             MinimizeApp::AddNeedMinimizeApp(appNode, MinimizeReason::MAX_APP_COUNT);
2007             return;
2008         }
2009     }
2010     WLOGD("no window needs to minimize");
2011 }
2012 
MinimizeOldestMainFloatingWindow(uint32_t windowId)2013 void WindowNodeContainer::MinimizeOldestMainFloatingWindow(uint32_t windowId)
2014 {
2015     if (maxMainFloatingWindowNumber_ <= 0) {
2016         WLOGD("There is no limit at The number of floating window");
2017         return;
2018     }
2019 
2020     auto windowNumber = GetMainFloatingWindowCount();
2021     if (windowNumber <= maxMainFloatingWindowNumber_) {
2022         WLOGD("The number of floating window is less then MaxFloatAppMainWindowNumber");
2023         return;
2024     }
2025     std::vector<sptr<WindowNode>> rootNodes = {
2026         appWindowNode_, aboveAppWindowNode_,
2027     };
2028     for (auto& root : rootNodes) {
2029         for (auto& appNode : root->children_) {
2030             WindowType windowType = appNode->GetWindowType();
2031             WindowMode windowMode = appNode->GetWindowMode();
2032             uint32_t winId = appNode->GetWindowId();
2033             if (windowId != winId && WindowHelper::IsMainFloatingWindow(windowType, windowMode)) {
2034                 MinimizeApp::AddNeedMinimizeApp(appNode, MinimizeReason::MAX_APP_COUNT);
2035                 return;
2036             }
2037         }
2038     }
2039     WLOGD("no window needs to minimize");
2040 }
2041 
ToggleShownStateForAllAppWindows( std::function<bool(uint32_t, WindowMode)> restoreFunc, bool restore)2042 WMError WindowNodeContainer::ToggleShownStateForAllAppWindows(
2043     std::function<bool(uint32_t, WindowMode)> restoreFunc, bool restore)
2044 {
2045     for (auto node : aboveAppWindowNode_->children_) {
2046         if (node->GetWindowType() == WindowType::WINDOW_TYPE_LAUNCHER_RECENT &&
2047             node->GetWindowMode() == WindowMode::WINDOW_MODE_FULLSCREEN && restore) {
2048             return WMError::WM_DO_NOTHING;
2049         }
2050     }
2051     // to do, backup reentry: 1.ToggleShownStateForAllAppWindows fast; 2.this display should reset backupWindowIds_.
2052     if (!restore && appWindowNode_->children_.empty() && !backupWindowIds_.empty()) {
2053         backupWindowIds_.clear();
2054         backupWindowMode_.clear();
2055         backupDisplaySplitWindowMode_.clear();
2056         backupDividerWindowRect_.clear();
2057     }
2058     if (!restore && !appWindowNode_->children_.empty() && backupWindowIds_.empty()) {
2059         WLOGD("backup");
2060         BackUpAllAppWindows();
2061     } else if (restore && !backupWindowIds_.empty()) {
2062         WLOGD("restore");
2063         RestoreAllAppWindows(restoreFunc);
2064     } else {
2065         WLOGD("do nothing because shown app windows is empty or backup windows is empty.");
2066     }
2067     WLOGD("ToggleShownStateForAllAppWindows");
2068     return WMError::WM_OK;
2069 }
2070 
BackUpAllAppWindows()2071 void WindowNodeContainer::BackUpAllAppWindows()
2072 {
2073     std::set<DisplayId> displayIdSet;
2074     backupWindowMode_.clear();
2075     backupDisplaySplitWindowMode_.clear();
2076     std::vector<sptr<WindowNode>> children = appWindowNode_->children_;
2077     for (auto& appNode : children) {
2078         if (!WindowHelper::IsMainWindow(appNode->GetWindowType())) {
2079             continue;
2080         }
2081         auto windowMode = appNode->GetWindowMode();
2082         backupWindowMode_[appNode->GetWindowId()] = windowMode;
2083         if (WindowHelper::IsSplitWindowMode(windowMode)) {
2084             backupDisplaySplitWindowMode_[appNode->GetDisplayId()].insert(windowMode);
2085         }
2086         displayIdSet.insert(appNode->GetDisplayId());
2087     }
2088     for (auto& appNode : children) {
2089         // exclude exceptional window
2090         if (!WindowHelper::IsMainWindow(appNode->GetWindowType())) {
2091             WLOGFE("is not main window, windowId:%{public}u", appNode->GetWindowId());
2092             continue;
2093         }
2094         // minimize window
2095         WLOGFD("minimize window, windowId:%{public}u", appNode->GetWindowId());
2096         backupWindowIds_.emplace_back(appNode->GetWindowId());
2097         WindowManagerService::GetInstance().RemoveWindow(appNode->GetWindowId(), true);
2098         wptr<IRemoteObject> abilityToken = appNode->abilityToken_;
2099         auto task = [abilityToken]() {
2100             auto token = abilityToken.promote();
2101             if (token == nullptr) {
2102                 WLOGFW("Ability token is null");
2103                 return;
2104             }
2105             AAFwk::AbilityManagerClient::GetInstance()->DoAbilityBackground(token,
2106                 static_cast<uint32_t>(WindowStateChangeReason::TOGGLING));
2107         };
2108         WindowInnerManager::GetInstance().PostTask(task, "DoAbilityBackground");
2109     }
2110     backupDividerWindowRect_.clear();
2111     for (auto displayId : displayIdSet) {
2112         auto windowPair = displayGroupController_->GetWindowPairByDisplayId(displayId);
2113         if (windowPair == nullptr || windowPair->GetDividerWindow() == nullptr) {
2114             continue;
2115         }
2116         backupDividerWindowRect_[displayId] = windowPair->GetDividerWindow()->GetWindowRect();
2117     }
2118 }
2119 
RestoreAllAppWindows(std::function<bool(uint32_t, WindowMode)> restoreFunc)2120 void WindowNodeContainer::RestoreAllAppWindows(std::function<bool(uint32_t, WindowMode)> restoreFunc)
2121 {
2122     std::vector<uint32_t> backupWindowIds(backupWindowIds_);
2123     auto displayIds = DisplayGroupInfo::GetInstance().GetAllDisplayIds();
2124     std::vector<sptr<WindowPair>> windowPairs;
2125     for (auto displayId : displayIds) {
2126         auto windowPair = displayGroupController_->GetWindowPairByDisplayId(displayId);
2127         if (windowPair != nullptr) {
2128             if (backupDisplaySplitWindowMode_[displayId].count(WindowMode::WINDOW_MODE_SPLIT_PRIMARY) > 0 &&
2129                 backupDisplaySplitWindowMode_[displayId].count(WindowMode::WINDOW_MODE_SPLIT_SECONDARY) > 0) {
2130                 windowPair->SetAllSplitAppWindowsRestoring(true);
2131             }
2132             windowPairs.emplace_back(windowPair);
2133         }
2134     }
2135     for (auto windowId: backupWindowIds) {
2136         if (!restoreFunc(windowId, backupWindowMode_[windowId])) {
2137             WLOGFE("restore %{public}u failed", windowId);
2138             continue;
2139         }
2140         WLOGFD("restore %{public}u", windowId);
2141     }
2142     for (auto windowPair : windowPairs) {
2143         windowPair->SetAllSplitAppWindowsRestoring(false);
2144     }
2145     layoutPolicy_->SetSplitDividerWindowRects(backupDividerWindowRect_);
2146     backupWindowIds_.clear();
2147     backupWindowMode_.clear();
2148     backupDividerWindowRect_.clear();
2149 }
2150 
IsAppWindowsEmpty() const2151 bool WindowNodeContainer::IsAppWindowsEmpty() const
2152 {
2153     return appWindowNode_->children_.empty();
2154 }
2155 
MinimizeAppNodeExceptOptions(MinimizeReason reason, const std::vector<uint32_t>& exceptionalIds, const std::vector<WindowMode>& exceptionalModes)2156 WMError WindowNodeContainer::MinimizeAppNodeExceptOptions(MinimizeReason reason,
2157     const std::vector<uint32_t>& exceptionalIds, const std::vector<WindowMode>& exceptionalModes)
2158 {
2159     if (appWindowNode_->children_.empty()) {
2160         return WMError::WM_OK;
2161     }
2162     for (auto& appNode : appWindowNode_->children_) {
2163         // exclude exceptional window
2164         if (std::find(exceptionalIds.begin(), exceptionalIds.end(), appNode->GetWindowId()) != exceptionalIds.end() ||
2165             std::find(exceptionalModes.begin(), exceptionalModes.end(),
2166                 appNode->GetWindowMode()) != exceptionalModes.end() ||
2167                 appNode->GetWindowType() != WindowType::WINDOW_TYPE_APP_MAIN_WINDOW) {
2168             continue;
2169         }
2170         MinimizeApp::AddNeedMinimizeApp(appNode, reason);
2171     }
2172     return WMError::WM_OK;
2173 }
2174 
MinimizeStructuredAppWindowsExceptSelf(const sptr<WindowNode>& node)2175 WMError WindowNodeContainer::MinimizeStructuredAppWindowsExceptSelf(const sptr<WindowNode>& node)
2176 {
2177     std::vector<uint32_t> exceptionalIds = { node->GetWindowId() };
2178     std::vector<WindowMode> exceptionalModes = { WindowMode::WINDOW_MODE_FLOATING, WindowMode::WINDOW_MODE_PIP };
2179     return MinimizeAppNodeExceptOptions(MinimizeReason::OTHER_WINDOW, exceptionalIds, exceptionalModes);
2180 }
2181 
SwitchLayoutPolicy(WindowLayoutMode dstMode, DisplayId displayId, bool reorder)2182 WMError WindowNodeContainer::SwitchLayoutPolicy(WindowLayoutMode dstMode, DisplayId displayId, bool reorder)
2183 {
2184     WLOGD("SwitchLayoutPolicy src: %{public}d dst: %{public}d, reorder: %{public}d, displayId: %{public}" PRIu64"",
2185         static_cast<uint32_t>(layoutMode_), static_cast<uint32_t>(dstMode), static_cast<uint32_t>(reorder), displayId);
2186     if (dstMode < WindowLayoutMode::BASE || dstMode >= WindowLayoutMode::END) {
2187         WLOGFE("invalid layout mode");
2188         return WMError::WM_ERROR_INVALID_PARAM;
2189     }
2190     auto windowPair = displayGroupController_->GetWindowPairByDisplayId(displayId);
2191     if (windowPair == nullptr) {
2192         WLOGFE("Window pair is nullptr");
2193         return WMError::WM_ERROR_NULLPTR;
2194     }
2195     if (layoutMode_ != dstMode) {
2196         if (layoutMode_ == WindowLayoutMode::CASCADE) {
2197             windowPair->Clear();
2198         }
2199         layoutMode_ = dstMode;
2200         layoutPolicy_ = layoutPolicies_[dstMode];
2201         layoutPolicy_->Launch();
2202         DumpScreenWindowTree();
2203     } else {
2204         WLOGI("Current layout mode is already: %{public}d", static_cast<uint32_t>(dstMode));
2205     }
2206     if (reorder) {
2207         windowPair->Clear();
2208         layoutPolicy_->Reorder();
2209         DumpScreenWindowTree();
2210     }
2211     NotifyIfSystemBarTintChanged(displayId);
2212     NotifyDockWindowStateChanged(displayId);
2213     return WMError::WM_OK;
2214 }
2215 
UpdateModeSupportInfoWhenKeyguardChange(const sptr<WindowNode>& node, bool up)2216 void WindowNodeContainer::UpdateModeSupportInfoWhenKeyguardChange(const sptr<WindowNode>& node, bool up)
2217 {
2218     if (!WindowHelper::IsWindowModeSupported(node->GetWindowProperty()->GetRequestModeSupportInfo(),
2219                                              WindowMode::WINDOW_MODE_SPLIT_PRIMARY)) {
2220         WLOGFD("window doesn't support split mode, winId: %{public}d", node->GetWindowId());
2221         return;
2222     }
2223     uint32_t modeSupportInfo;
2224     if (up) {
2225         modeSupportInfo = node->GetModeSupportInfo() & (~WindowModeSupport::WINDOW_MODE_SUPPORT_SPLIT_PRIMARY);
2226     } else {
2227         modeSupportInfo = node->GetModeSupportInfo() | WindowModeSupport::WINDOW_MODE_SUPPORT_SPLIT_PRIMARY;
2228     }
2229     node->SetModeSupportInfo(modeSupportInfo);
2230     if (node->GetWindowToken() != nullptr) {
2231         node->GetWindowToken()->UpdateWindowModeSupportInfo(modeSupportInfo);
2232     }
2233 }
2234 
RaiseInputMethodWindowPriorityIfNeeded(const sptr<WindowNode>& node) const2235 void WindowNodeContainer::RaiseInputMethodWindowPriorityIfNeeded(const sptr<WindowNode>& node) const
2236 {
2237     if (node->GetWindowType() != WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT) {
2238         return;
2239     }
2240 
2241     if (isScreenLocked_) {
2242         node->priority_ = zorderPolicy_->GetWindowPriority(
2243             WindowType::WINDOW_TYPE_KEYGUARD) + 2; // 2: higher than keyguard and show when locked window
2244         WLOGD("Raise input method float window priority when screen locked.");
2245         return;
2246     }
2247 
2248     auto callingWindowId = node->GetCallingWindow();
2249     auto callingWindow = FindWindowNodeById(callingWindowId);
2250     if (callingWindowId == focusedWindow_ && callingWindow != nullptr) {
2251         auto callingWindowType = callingWindow->GetWindowType();
2252         auto callingWindowPriority = zorderPolicy_->GetWindowPriority(callingWindowType);
2253         auto inputMethodPriority = zorderPolicy_->GetWindowPriority(WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT);
2254 
2255         node->priority_ = (inputMethodPriority < callingWindowPriority) ?
2256             (callingWindowPriority + 1) : inputMethodPriority;
2257         WLOGFD("Reset input method float window priority to %{public}d.", node->priority_);
2258         return;
2259     }
2260 
2261     auto focusWindow = FindWindowNodeById(focusedWindow_);
2262     if (focusWindow != nullptr && focusWindow->GetWindowType() == WindowType::WINDOW_TYPE_PANEL) {
2263         node->priority_ = zorderPolicy_->GetWindowPriority(WindowType::WINDOW_TYPE_PANEL) + 1;
2264         WLOGFD("The input method float window should be higher than panel");
2265     }
2266 }
2267 
ReZOrderShowWhenLockedWindows(bool up)2268 void WindowNodeContainer::ReZOrderShowWhenLockedWindows(bool up)
2269 {
2270     WLOGD("Keyguard change %{public}u, re-zorder showWhenLocked window", up);
2271     std::vector<sptr<WindowNode>> needReZOrderNodes;
2272     auto& srcRoot = up ? appWindowNode_ : aboveAppWindowNode_;
2273     auto& dstRoot = up ? aboveAppWindowNode_ : appWindowNode_;
2274 
2275     auto dstPriority = up ? zorderPolicy_->GetWindowPriority(WindowType::WINDOW_TYPE_KEYGUARD) + 1 :
2276         zorderPolicy_->GetWindowPriority(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW);
2277 
2278     for (auto iter = srcRoot->children_.begin(); iter != srcRoot->children_.end();) {
2279         if ((*iter)->GetWindowFlags() & static_cast<uint32_t>(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED)) {
2280             needReZOrderNodes.emplace_back(*iter);
2281             iter = srcRoot->children_.erase(iter);
2282         } else {
2283             iter++;
2284         }
2285     }
2286     const int32_t floatingPriorityOffset = 1;
2287     for (auto& needReZOrderNode : needReZOrderNodes) {
2288         needReZOrderNode->priority_ = dstPriority;
2289         needReZOrderNode->parent_ = dstRoot;
2290         if (WindowHelper::IsMainFloatingWindow(needReZOrderNode->GetWindowType(),
2291             needReZOrderNode->GetWindowMode()) && isFloatWindowAboveFullWindow_) {
2292             needReZOrderNode->priority_ = dstPriority + floatingPriorityOffset;
2293         }
2294         auto parentNode = needReZOrderNode->parent_;
2295         auto position = parentNode->children_.end();
2296         for (auto iter = parentNode->children_.begin(); iter < parentNode->children_.end(); ++iter) {
2297             if ((*iter)->priority_ > needReZOrderNode->priority_) {
2298                 position = iter;
2299                 break;
2300             }
2301         }
2302 
2303         UpdateModeSupportInfoWhenKeyguardChange(needReZOrderNode, up);
2304 
2305         parentNode->children_.insert(position, needReZOrderNode);
2306         if (up && WindowHelper::IsSplitWindowMode(needReZOrderNode->GetWindowMode())) {
2307             needReZOrderNode->GetWindowProperty()->ResumeLastWindowMode();
2308             // when change mode, need to reset shadow and radius
2309             WindowSystemEffect::SetWindowEffect(needReZOrderNode);
2310             if (needReZOrderNode->GetWindowToken() != nullptr) {
2311                 needReZOrderNode->GetWindowToken()->UpdateWindowMode(needReZOrderNode->GetWindowMode());
2312             }
2313             auto windowPair = displayGroupController_->GetWindowPairByDisplayId(needReZOrderNode->GetDisplayId());
2314             if (windowPair == nullptr) {
2315                 WLOGFE("Window pair is nullptr");
2316                 return;
2317             }
2318             windowPair->UpdateIfSplitRelated(needReZOrderNode);
2319         }
2320         WLOGD("window %{public}u re-zorder when keyguard change %{public}u", needReZOrderNode->GetWindowId(), up);
2321     }
2322 }
2323 
ReZOrderShowWhenLockedWindowIfNeeded(const sptr<WindowNode>& node)2324 void WindowNodeContainer::ReZOrderShowWhenLockedWindowIfNeeded(const sptr<WindowNode>& node)
2325 {
2326     if (!(node->GetWindowFlags() & static_cast<uint32_t>(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED)) ||
2327         !isScreenLocked_) {
2328         return;
2329     }
2330 
2331     ReZOrderShowWhenLockedWindows(true);
2332     WLOGI("ShowWhenLocked window %{public}u re-zorder to up", node->GetWindowId());
2333 }
2334 
RaiseShowWhenLockedWindowIfNeeded(const sptr<WindowNode>& node)2335 void WindowNodeContainer::RaiseShowWhenLockedWindowIfNeeded(const sptr<WindowNode>& node)
2336 {
2337     // if keyguard window show, raise show when locked windows
2338     if (node->GetWindowType() == WindowType::WINDOW_TYPE_KEYGUARD) {
2339         ReZOrderShowWhenLockedWindows(true);
2340         return;
2341     }
2342 
2343     // if show when locked window show, raise itself when exist keyguard
2344     if (!(node->GetWindowFlags() & static_cast<uint32_t>(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED)) ||
2345         !isScreenLocked_) {
2346         return;
2347     }
2348 
2349     node->priority_ = zorderPolicy_->GetWindowPriority(WindowType::WINDOW_TYPE_KEYGUARD) + 1;
2350     node->parent_ = aboveAppWindowNode_;
2351     if (WindowHelper::IsSplitWindowMode(node->GetWindowMode())) {
2352         node->GetWindowProperty()->ResumeLastWindowMode();
2353         // when change mode, need to reset shadow and radius
2354         WindowSystemEffect::SetWindowEffect(node);
2355         if (node->GetWindowToken() != nullptr) {
2356             node->GetWindowToken()->UpdateWindowMode(node->GetWindowMode());
2357         }
2358     }
2359     WLOGI("ShowWhenLocked window %{public}u raise itself", node->GetWindowId());
2360 }
2361 
DropShowWhenLockedWindowIfNeeded(const sptr<WindowNode>& node)2362 void WindowNodeContainer::DropShowWhenLockedWindowIfNeeded(const sptr<WindowNode>& node)
2363 {
2364     // if keyguard window hide, drop show when locked windows
2365     if (node->GetWindowType() == WindowType::WINDOW_TYPE_KEYGUARD) {
2366         ReZOrderShowWhenLockedWindows(false);
2367         AssignZOrder();
2368     }
2369 }
2370 
TraverseWindowTree(const WindowNodeOperationFunc& func, bool isFromTopToBottom) const2371 void WindowNodeContainer::TraverseWindowTree(const WindowNodeOperationFunc& func, bool isFromTopToBottom) const
2372 {
2373     std::vector<sptr<WindowNode>> rootNodes = { belowAppWindowNode_, appWindowNode_, aboveAppWindowNode_ };
2374     if (isFromTopToBottom) {
2375         std::reverse(rootNodes.begin(), rootNodes.end());
2376     }
2377 
2378     for (const auto& node : rootNodes) {
2379         if (isFromTopToBottom) {
2380             for (auto iter = node->children_.rbegin(); iter != node->children_.rend(); ++iter) {
2381                 if (TraverseFromTopToBottom(*iter, func)) {
2382                     return;
2383                 }
2384             }
2385         } else {
2386             for (auto iter = node->children_.begin(); iter != node->children_.end(); ++iter) {
2387                 if (TraverseFromBottomToTop(*iter, func)) {
2388                     return;
2389                 }
2390             }
2391         }
2392     }
2393 }
2394 
TraverseFromTopToBottom(sptr<WindowNode> node, const WindowNodeOperationFunc& func) const2395 bool WindowNodeContainer::TraverseFromTopToBottom(sptr<WindowNode> node, const WindowNodeOperationFunc& func) const
2396 {
2397     if (node == nullptr) {
2398         return false;
2399     }
2400     auto iterBegin = node->children_.rbegin();
2401     for (; iterBegin != node->children_.rend(); ++iterBegin) {
2402         if ((*iterBegin)->priority_ <= 0) {
2403             break;
2404         }
2405         if (func(*iterBegin)) {
2406             return true;
2407         }
2408     }
2409     if (func(node)) {
2410         return true;
2411     }
2412     for (; iterBegin != node->children_.rend(); ++iterBegin) {
2413         if (func(*iterBegin)) {
2414             return true;
2415         }
2416     }
2417     return false;
2418 }
2419 
TraverseFromBottomToTop(sptr<WindowNode> node, const WindowNodeOperationFunc& func) const2420 bool WindowNodeContainer::TraverseFromBottomToTop(sptr<WindowNode> node, const WindowNodeOperationFunc& func) const
2421 {
2422     if (node == nullptr) {
2423         return false;
2424     }
2425     auto iterBegin = node->children_.begin();
2426     for (; iterBegin != node->children_.end(); ++iterBegin) {
2427         if ((*iterBegin)->priority_ >= 0) {
2428             break;
2429         }
2430         if (func(*iterBegin)) {
2431             return true;
2432         }
2433     }
2434     if (func(node)) {
2435         return true;
2436     }
2437     for (; iterBegin != node->children_.end(); ++iterBegin) {
2438         if (func(*iterBegin)) {
2439             return true;
2440         }
2441     }
2442     return false;
2443 }
2444 
GetDisplayGroupRect() const2445 Rect WindowNodeContainer::GetDisplayGroupRect() const
2446 {
2447     return layoutPolicy_->GetDisplayGroupRect();
2448 }
2449 
UpdateSizeChangeReason(sptr<WindowNode>& node, WindowMode srcMode, WindowMode dstMode)2450 void WindowNodeContainer::UpdateSizeChangeReason(sptr<WindowNode>& node, WindowMode srcMode, WindowMode dstMode)
2451 {
2452     if ((srcMode == WindowMode::WINDOW_MODE_FULLSCREEN) && (dstMode == WindowMode::WINDOW_MODE_FLOATING)) {
2453         node->SetWindowSizeChangeReason(WindowSizeChangeReason::RECOVER);
2454     } else if (dstMode == WindowMode::WINDOW_MODE_FULLSCREEN) {
2455         node->SetWindowSizeChangeReason(WindowSizeChangeReason::MAXIMIZE);
2456         if (srcMode == WindowMode::WINDOW_MODE_FLOATING) {
2457             node->SetRequestRect(node->GetWindowRect());
2458         }
2459     } else if (WindowHelper::IsFullScreenWindow(srcMode) && WindowHelper::IsSplitWindowMode(dstMode)) {
2460         node->SetWindowSizeChangeReason(WindowSizeChangeReason::FULL_TO_SPLIT);
2461     } else if (WindowHelper::IsSplitWindowMode(srcMode) && WindowHelper::IsFullScreenWindow(dstMode)) {
2462         node->SetWindowSizeChangeReason(WindowSizeChangeReason::SPLIT_TO_FULL);
2463     } else {
2464         node->SetWindowSizeChangeReason(WindowSizeChangeReason::RESIZE);
2465     }
2466 }
2467 
SetWindowMode(sptr<WindowNode>& node, WindowMode dstMode)2468 WMError WindowNodeContainer::SetWindowMode(sptr<WindowNode>& node, WindowMode dstMode)
2469 {
2470     if (node == nullptr) {
2471         WLOGFE("could not find window");
2472         return WMError::WM_ERROR_NULLPTR;
2473     }
2474     WindowMode srcMode = node->GetWindowMode();
2475     if (WindowHelper::IsSplitWindowMode(dstMode) && isScreenLocked_ &&
2476         (node->GetWindowFlags() & static_cast<uint32_t>(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED))) {
2477         return WMError::WM_ERROR_INVALID_PARAM;
2478     }
2479 
2480     auto windowPair = displayGroupController_->GetWindowPairByDisplayId(node->GetDisplayId());
2481     if (windowPair == nullptr) {
2482         WLOGFE("Window pair is nullptr");
2483         return WMError::WM_ERROR_NULLPTR;
2484     }
2485 
2486     WindowPairStatus status = windowPair->GetPairStatus();
2487     // when status is single primary or single secondary, split node is abandoned to set mode
2488     if (node->IsSplitMode() && (status == WindowPairStatus::SINGLE_PRIMARY ||
2489         status == WindowPairStatus::SINGLE_SECONDARY)) {
2490         return WMError::WM_ERROR_INVALID_OPERATION;
2491     }
2492     WMError res = WMError::WM_OK;
2493     UpdateSizeChangeReason(node, srcMode, dstMode);
2494     node->SetWindowMode(dstMode);
2495     windowPair->UpdateIfSplitRelated(node);
2496 
2497     if (WindowHelper::IsMainWindow(node->GetWindowType())) {
2498         if (WindowHelper::IsFloatingWindow(node->GetWindowMode())) {
2499             NotifyDockWindowStateChanged(node, true);
2500         } else {
2501             NotifyDockWindowStateChanged(node, false);
2502         }
2503     }
2504 
2505     if (node->GetWindowMode() == WindowMode::WINDOW_MODE_FULLSCREEN &&
2506         WindowHelper::IsAppWindow(node->GetWindowType())) {
2507         // minimize other app window.
2508         res = MinimizeStructuredAppWindowsExceptSelf(node);
2509         if (res != WMError::WM_OK) {
2510             return res;
2511         }
2512     }
2513     // when change mode, need to reset shadow and radius.
2514     WindowSystemEffect::SetWindowEffect(node);
2515 
2516     // when change mode, need to reset MainFloatingWindow ZOrder.
2517     ResetWindowZOrderPriorityWhenSetMode(node, dstMode, srcMode);
2518     MinimizeOldestMainFloatingWindow(node->GetWindowId());
2519 
2520     if (node->GetWindowToken() != nullptr) {
2521         node->GetWindowToken()->UpdateWindowMode(node->GetWindowMode());
2522     }
2523     res = UpdateWindowNode(node, WindowUpdateReason::UPDATE_MODE);
2524     if (res != WMError::WM_OK) {
2525         WLOGFE("Set window mode failed, update node failed");
2526         return res;
2527     }
2528     return WMError::WM_OK;
2529 }
2530 
ResetWindowZOrderPriorityWhenSetMode(sptr<WindowNode>& node, const WindowMode& dstMode, const WindowMode& srcMode)2531 void WindowNodeContainer::ResetWindowZOrderPriorityWhenSetMode(sptr<WindowNode>& node,
2532     const WindowMode& dstMode, const WindowMode& srcMode)
2533 {
2534     if (!isFloatWindowAboveFullWindow_) {
2535         return;
2536     }
2537 
2538     // reset node zorder priority.
2539     if (WindowHelper::IsMainFloatingWindow(node->GetWindowType(), srcMode)) {
2540         auto basePriority = zorderPolicy_->GetWindowPriority(node->GetWindowType());
2541         if (isScreenLocked_ &&
2542             (node->GetWindowFlags() & static_cast<uint32_t>(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED))) {
2543             basePriority = zorderPolicy_->GetWindowPriority(WindowType::WINDOW_TYPE_KEYGUARD) + 1;
2544         }
2545         node->priority_ = basePriority;
2546     }
2547 
2548     if (!WindowHelper::IsMainFloatingWindow(node->GetWindowType(), srcMode) &&
2549         !WindowHelper::IsMainFloatingWindow(node->GetWindowType(), dstMode) &&
2550         !WindowHelper::IsSplitWindowMode(srcMode) &&
2551         !WindowHelper::IsSplitWindowMode(dstMode)) {
2552         return;
2553     }
2554 
2555     // When set mode, all floating window should be checked and raise
2556     ResetAllMainFloatingWindowZOrder(node->parent_);
2557     if (node->parent_ != nullptr && node->GetWindowId() == focusedWindow_ &&
2558         WindowHelper::IsMainFloatingWindow(node->GetWindowType(), dstMode)) {
2559         // if current node is mainFloatingWIndow and foucsedWindow, it should be raised to top.
2560         RaiseWindowToTop(node->GetWindowId(), node->parent_->children_);
2561     }
2562     AssignZOrder();
2563 }
2564 
GetModeChangeHotZones(DisplayId displayId, ModeChangeHotZones& hotZones, const ModeChangeHotZonesConfig& config)2565 void WindowNodeContainer::GetModeChangeHotZones(DisplayId displayId, ModeChangeHotZones& hotZones,
2566     const ModeChangeHotZonesConfig& config)
2567 {
2568     const auto& displayRect = DisplayGroupInfo::GetInstance().GetDisplayRect(displayId);
2569 
2570     hotZones.fullscreen_.width_ = displayRect.width_;
2571     hotZones.fullscreen_.height_ = config.fullscreenRange_;
2572 
2573     hotZones.primary_.width_ = config.primaryRange_;
2574     hotZones.primary_.height_ = displayRect.height_;
2575 
2576     hotZones.secondary_.posX_ = static_cast<int32_t>(displayRect.width_) - config.secondaryRange_;
2577     hotZones.secondary_.width_ = config.secondaryRange_;
2578     hotZones.secondary_.height_ = displayRect.height_;
2579 }
2580 
UpdateCameraFloatWindowStatus(const sptr<WindowNode>& node, bool isShowing)2581 void WindowNodeContainer::UpdateCameraFloatWindowStatus(const sptr<WindowNode>& node, bool isShowing)
2582 {
2583     if (node->GetWindowType() == WindowType::WINDOW_TYPE_FLOAT_CAMERA) {
2584         WindowManagerAgentController::GetInstance().UpdateCameraFloatWindowStatus(node->GetAccessTokenId(), isShowing);
2585     }
2586 }
2587 
GetCurrentLayoutMode() const2588 WindowLayoutMode WindowNodeContainer::GetCurrentLayoutMode() const
2589 {
2590     return layoutMode_;
2591 }
2592 
RemoveSingleUserWindowNodes(int accountId)2593 void WindowNodeContainer::RemoveSingleUserWindowNodes(int accountId)
2594 {
2595     std::vector<sptr<WindowNode>> windowNodes;
2596     TraverseContainer(windowNodes);
2597     WLOGI("%{public}d", accountId);
2598     for (auto& windowNode : windowNodes) {
2599         int windowAccountId = windowNode->GetCallingUid() / UID_TRANSFROM_DIVISOR;
2600         if (windowAccountId < UID_MIN || windowAccountId == accountId) {
2601             WLOGD("skiped window %{public}s, windowId %{public}d uid %{public}d",
2602                 windowNode->GetWindowName().c_str(), windowNode->GetWindowId(), windowNode->GetCallingUid());
2603             continue;
2604         }
2605         WLOGD("remove window %{public}s, windowId %{public}d uid %{public}d",
2606             windowNode->GetWindowName().c_str(), windowNode->GetWindowId(), windowNode->GetCallingUid());
2607         windowNode->GetWindowProperty()->SetAnimationFlag(static_cast<uint32_t>(WindowAnimation::NONE));
2608         if (windowNode->GetWindowToken()) {
2609             if (windowNode->surfaceNode_ != nullptr) {
2610                 windowNode->surfaceNode_->SetVisible(true);
2611             }
2612             windowNode->GetWindowToken()->UpdateWindowState(WindowState::STATE_HIDDEN);
2613         }
2614     }
2615 }
2616 
TakeWindowPairSnapshot(DisplayId displayId)2617 bool WindowNodeContainer::TakeWindowPairSnapshot(DisplayId displayId)
2618 {
2619     auto windowPair = displayGroupController_->GetWindowPairByDisplayId(displayId);
2620     return windowPair == nullptr ? false : windowPair->TakePairSnapshot();
2621 }
2622 
ClearWindowPairSnapshot(DisplayId displayId)2623 void WindowNodeContainer::ClearWindowPairSnapshot(DisplayId displayId)
2624 {
2625     auto windowPair = displayGroupController_->GetWindowPairByDisplayId(displayId);
2626     if (windowPair == nullptr) {
2627         WLOGFE("Window pair is nullptr");
2628         return;
2629     }
2630     windowPair->ClearPairSnapshot();
2631 }
2632 
SetWindowPairFrameGravity(DisplayId displayId, Gravity gravity)2633 void WindowNodeContainer::SetWindowPairFrameGravity(DisplayId displayId, Gravity gravity)
2634 {
2635     auto windowPair = displayGroupController_->GetWindowPairByDisplayId(displayId);
2636     if (windowPair == nullptr) {
2637         WLOGFE("Window pair is nullptr");
2638         return;
2639     }
2640     std::vector<sptr<WindowNode>> windowNodes = windowPair->GetPairedWindows();
2641     for (auto& windowNode : windowNodes) {
2642         if (windowNode->surfaceNode_) {
2643             windowNode->surfaceNode_->SetFrameGravity(gravity);
2644         }
2645     }
2646 }
2647 
IsScreenLocked()2648 bool WindowNodeContainer::IsScreenLocked()
2649 {
2650     return isScreenLocked_;
2651 }
2652 
GetAnimateTransactionEnabled()2653 bool WindowNodeContainer::GetAnimateTransactionEnabled()
2654 {
2655     return isAnimateTransactionEnabled_;
2656 }
2657 } // namespace Rosen
2658 } // namespace OHOS
2659