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