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