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
53namespace OHOS {
54namespace Rosen {
55namespace {
56constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "Container"};
57constexpr int WINDOW_NAME_MAX_LENGTH = 10;
58constexpr uint32_t MAX_BRIGHTNESS = 255;
59constexpr uint32_t SPLIT_WINDOWS_CNT = 2;
60constexpr uint32_t EXIT_SPLIT_POINTS_NUMBER = 2;
61constexpr int UID_TRANSFROM_DIVISOR = 200000;
62constexpr int UID_MIN = 100;
63}
64AnimationConfig WindowNodeContainer::animationConfig_;
65bool WindowNodeContainer::isFloatWindowAboveFullWindow_ = false;
66uint32_t WindowNodeContainer::maxMainFloatingWindowNumber_ = 100;
67bool WindowNodeContainer::isAnimateTransactionEnabled_ = false;
68WindowUIType WindowNodeContainer::windowUIType_ = WindowUIType::INVALID_WINDOW;
69
70WindowNodeContainer::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
101WindowNodeContainer::~WindowNodeContainer()
102{
103    Destroy();
104}
105
106uint32_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
120uint32_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
136WMError 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
180WMError 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
200WMError 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
211AnimationConfig& WindowNodeContainer::GetAnimationConfigRef()
212{
213    return animationConfig_;
214}
215
216void 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
244WMError 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
310void 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
335WMError 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
354void 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
366void 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
383void 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
402void 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
411WMError 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
457void 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
495void WindowNodeContainer::SetDisplayOrientationFromWindow(sptr<WindowNode>& node, bool withAnimation)
496{
497    DisplayManagerServiceInner::GetInstance().SetOrientationFromWindow(node->GetDisplayId(),
498        node->GetRequestedOrientation(), withAnimation);
499}
500
501void 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
513void 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
527uint32_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
538void WindowNodeContainer::SetConfigMainFloatingWindowAbove(bool isAbove)
539{
540    isFloatWindowAboveFullWindow_ = isAbove;
541}
542
543void WindowNodeContainer::SetMaxMainFloatingWindowNumber(uint32_t maxNumber)
544{
545    maxMainFloatingWindowNumber_ = maxNumber;
546}
547
548void 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
579void 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
610WMError 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
629WMError 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
663void 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
684void 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
719bool 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
744void 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
763void 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
776bool WindowNodeContainer::IsWindowFollowParent(WindowType type)
777{
778    if (windowUIType_ != WindowUIType::PHONE_WINDOW) {
779        return false;
780    }
781    return WindowHelper::IsWindowFollowParent(type);
782}
783
784bool 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
853bool 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
923const 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
940sptr<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
956sptr<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
974void 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
1020void 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
1035void 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
1071void 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
1101WMError 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
1118uint32_t WindowNodeContainer::GetFocusWindow() const
1119{
1120    return focusedWindow_;
1121}
1122
1123WMError 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
1139void WindowNodeContainer::SetDisplayBrightness(float brightness)
1140{
1141    displayBrightness_ = brightness;
1142}
1143
1144float WindowNodeContainer::GetDisplayBrightness() const
1145{
1146    return displayBrightness_;
1147}
1148
1149void WindowNodeContainer::SetBrightnessWindow(uint32_t windowId)
1150{
1151    brightnessWindow_ = windowId;
1152}
1153
1154uint32_t WindowNodeContainer::GetBrightnessWindow() const
1155{
1156    return brightnessWindow_;
1157}
1158
1159uint32_t WindowNodeContainer::ToOverrideBrightness(float brightness)
1160{
1161    return static_cast<uint32_t>(brightness * MAX_BRIGHTNESS);
1162}
1163
1164uint32_t WindowNodeContainer::GetActiveWindow() const
1165{
1166    return activeWindow_;
1167}
1168
1169sptr<WindowLayoutPolicy> WindowNodeContainer::GetLayoutPolicy() const
1170{
1171    return layoutPolicy_;
1172}
1173
1174sptr<AvoidAreaController> WindowNodeContainer::GetAvoidController() const
1175{
1176    return avoidController_;
1177}
1178
1179sptr<DisplayGroupController> WindowNodeContainer::GetDisplayGroupController() const
1180{
1181    return displayGroupController_;
1182}
1183
1184sptr<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
1196void 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
1229bool 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
1239bool WindowNodeContainer::IsSplitImmersiveNode(sptr<WindowNode> node) const
1240{
1241    auto type = node->GetWindowType();
1242    return node->IsSplitMode() || type == WindowType::WINDOW_TYPE_DOCK_SLICE;
1243}
1244
1245std::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
1297void 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
1313void WindowNodeContainer::BeforeProcessWindowAvoidAreaChangeWhenDisplayChange() const
1314{
1315    avoidController_->SetFlagForProcessWindowChange(true);
1316}
1317
1318void 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
1331void 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
1353void 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
1375void 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
1397void 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
1459void 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
1483void 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
1507void 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
1529void WindowNodeContainer::UpdateAvoidAreaListener(sptr<WindowNode>& windowNode, bool haveAvoidAreaListener)
1530{
1531    avoidController_->UpdateAvoidAreaListener(windowNode, haveAvoidAreaListener);
1532}
1533
1534bool 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
1556void 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
1575void 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
1594void 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
1608void 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
1627AvoidArea 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
1635bool 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
1649void 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
1676void 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
1696bool WindowNodeContainer::IsVerticalDisplay(DisplayId displayId) const
1697{
1698    return DisplayGroupInfo::GetInstance().GetDisplayRect(displayId).width_ <
1699        DisplayGroupInfo::GetInstance().GetDisplayRect(displayId).height_;
1700}
1701
1702void 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
1715void 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
1723void 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
1742void 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
1757sptr<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
1767void 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
1783WMError 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
1826sptr<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
1845sptr<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
1861sptr<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
1906bool 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
1919bool 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
1933void 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
1943void 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
1953sptr<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
1967bool 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
1981bool 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
1996void 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
2013void 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
2042WMError 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
2071void 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
2120void 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
2151bool WindowNodeContainer::IsAppWindowsEmpty() const
2152{
2153    return appWindowNode_->children_.empty();
2154}
2155
2156WMError 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
2175WMError 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
2182WMError 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
2216void 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
2235void 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
2268void 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
2324void 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
2335void 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
2362void 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
2371void 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
2395bool 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
2420bool 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
2445Rect WindowNodeContainer::GetDisplayGroupRect() const
2446{
2447    return layoutPolicy_->GetDisplayGroupRect();
2448}
2449
2450void 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
2468WMError 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
2531void 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
2565void 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
2581void 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
2588WindowLayoutMode WindowNodeContainer::GetCurrentLayoutMode() const
2589{
2590    return layoutMode_;
2591}
2592
2593void 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
2617bool WindowNodeContainer::TakeWindowPairSnapshot(DisplayId displayId)
2618{
2619    auto windowPair = displayGroupController_->GetWindowPairByDisplayId(displayId);
2620    return windowPair == nullptr ? false : windowPair->TakePairSnapshot();
2621}
2622
2623void 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
2633void 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
2648bool WindowNodeContainer::IsScreenLocked()
2649{
2650    return isScreenLocked_;
2651}
2652
2653bool WindowNodeContainer::GetAnimateTransactionEnabled()
2654{
2655    return isAnimateTransactionEnabled_;
2656}
2657} // namespace Rosen
2658} // namespace OHOS
2659