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