• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 "remote_animation.h"
17 
18 #include <ability_manager_client.h>
19 #include <common/rs_rect.h>
20 #include <hisysevent.h>
21 #include <hitrace_meter.h>
22 #include <string>
23 #include <transaction/rs_transaction.h>
24 
25 #include "display_group_info.h"
26 #include "minimize_app.h"
27 #include "parameters.h"
28 #include "starting_window.h"
29 #include "surface_draw.h"
30 #include "window_helper.h"
31 #include "window_inner_manager.h"
32 #include "window_manager_hilog.h"
33 #include "window_manager_service_utils.h"
34 #include "window_system_effect.h"
35 #include "zidl/ressched_report.h"
36 #ifdef SOC_PERF_ENABLE
37 #include "socperf_client.h"
38 #endif
39 
40 namespace OHOS {
41 namespace Rosen {
42 namespace {
43 constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "RemoteAnimation"};
44 const std::string ANIMATION_TIME_OUT_TASK = "remote_animation_time_out_task";
45 constexpr int64_t ANIMATION_TIME_OUT_MILLISECONDS = 3000; // 3000 is max time
46 }
47 bool RemoteAnimation::isRemoteAnimationEnable_ = true;
48 std::atomic<uint32_t> RemoteAnimation::allocationId_ = 0;
49 sptr<RSIWindowAnimationController> RemoteAnimation::windowAnimationController_ = nullptr;
50 std::weak_ptr<AppExecFwk::EventHandler> RemoteAnimation::wmsTaskHandler_;
51 wptr<WindowRoot> RemoteAnimation::windowRoot_;
52 bool RemoteAnimation::animationFirst_ = false;
53 wptr<WindowController> RemoteAnimation::windowController_ = nullptr;
54 
55 std::map<TransitionReason, TransitionEvent> eventMap_ = {
56     {TransitionReason::CLOSE, TransitionEvent::CLOSE},
57     {TransitionReason::MINIMIZE, TransitionEvent::MINIMIZE},
58     {TransitionReason::BACK_TRANSITION, TransitionEvent::BACK_TRANSITION},
59     {TransitionReason::CLOSE_BUTTON, TransitionEvent::CLOSE_BUTTON},
60     {TransitionReason::BACKGROUND_TRANSITION, TransitionEvent::BACKGROUND_TRANSITION}
61 };
62 
SetAnimationFirst(bool animationFirst)63 void RemoteAnimation::SetAnimationFirst(bool animationFirst)
64 {
65     animationFirst_ = animationFirst;
66     WLOGFI("RSWindowAnimation:animationFirst: %{public}u!", static_cast<uint32_t>(animationFirst_));
67 }
68 
IsRemoteAnimationEnabledAndFirst(DisplayId displayId)69 bool RemoteAnimation::IsRemoteAnimationEnabledAndFirst(DisplayId displayId)
70 {
71     return animationFirst_ && CheckRemoteAnimationEnabled(displayId);
72 }
73 
SetWindowAnimationController(const sptr<RSIWindowAnimationController> & controller)74 WMError RemoteAnimation::SetWindowAnimationController(const sptr<RSIWindowAnimationController>& controller)
75 {
76     WLOGFI("RSWindowAnimation: set window animation controller!");
77     if (!isRemoteAnimationEnable_) {
78         WLOGFE("RSWindowAnimation: failed to set window animation controller, remote animation is not enabled");
79         return WMError::WM_ERROR_NO_REMOTE_ANIMATION;
80     }
81     if (controller == nullptr) {
82         WLOGFE("RSWindowAnimation: failed to set window animation controller, controller is null!");
83         return WMError::WM_ERROR_NULLPTR;
84     }
85 
86     if (windowAnimationController_ != nullptr) {
87         WLOGFI("RSWindowAnimation: maybe user switch!");
88     }
89 
90     windowAnimationController_ = controller;
91     auto winRoot = windowRoot_.promote();
92     if (winRoot) {
93         auto wallpaperNode = winRoot->FindWallpaperWindow();
94         if (wallpaperNode) {
95             NotifyAnimationUpdateWallpaper(wallpaperNode);
96         } else {
97             WLOGFW("Cannot find wallpaper window!");
98         }
99     }
100     return WMError::WM_OK;
101 }
102 
SetMainTaskHandler(std::shared_ptr<AppExecFwk::EventHandler> handler)103 void RemoteAnimation::SetMainTaskHandler(std::shared_ptr<AppExecFwk::EventHandler> handler)
104 {
105     wmsTaskHandler_ = handler;
106 }
107 
SetWindowControllerAndRoot(const sptr<WindowController> & windowController,const sptr<WindowRoot> & windowRoot)108 void RemoteAnimation::SetWindowControllerAndRoot(const sptr<WindowController>& windowController,
109     const sptr<WindowRoot>& windowRoot)
110 {
111     windowController_ = windowController;
112     windowRoot_ = windowRoot;
113 }
114 
CheckAnimationController()115 bool RemoteAnimation::CheckAnimationController()
116 {
117     if (windowAnimationController_ == nullptr) {
118         WLOGFD("RSWindowAnimation: windowAnimationController_ null!");
119         return false;
120     }
121     return true;
122 }
123 
CheckRemoteAnimationEnabled(DisplayId displayId)124 bool RemoteAnimation::CheckRemoteAnimationEnabled(DisplayId displayId)
125 {
126     // When the screen is locked, remote animation cannot take effect because the launcher is frozen.
127     auto winRoot = windowRoot_.promote();
128     if (winRoot == nullptr) {
129         return false;
130     }
131     auto container = winRoot->GetOrCreateWindowNodeContainer(displayId);
132     if (container == nullptr || container->IsScreenLocked()) {
133         return false;
134     }
135     return CheckAnimationController();
136 }
137 
CheckTransition(sptr<WindowTransitionInfo> srcInfo,const sptr<WindowNode> & srcNode,sptr<WindowTransitionInfo> dstInfo,const sptr<WindowNode> & dstNode)138 bool RemoteAnimation::CheckTransition(sptr<WindowTransitionInfo> srcInfo, const sptr<WindowNode>& srcNode,
139     sptr<WindowTransitionInfo> dstInfo, const sptr<WindowNode>& dstNode)
140 {
141     if (srcNode == nullptr && dstNode == nullptr) {
142         WLOGFE("RSWindowAnimation: srcNode and dstNode are nullptr");
143         return false;
144     }
145 
146     if (srcNode != nullptr && !srcNode->leashWinSurfaceNode_ && !srcNode->surfaceNode_) {
147         WLOGFE("RSWindowAnimation: srcNode has no surface, winId: %{public}u", srcNode->GetWindowId());
148         return false;
149     }
150 
151     if (dstNode != nullptr && !dstNode->leashWinSurfaceNode_ && !dstNode->surfaceNode_) {
152         WLOGFE("RSWindowAnimation: dstNode has no surface, winId: %{public}u", dstNode->GetWindowId());
153         return false;
154     }
155 
156     // check support window mode when one app starts another app
157     if ((dstNode != nullptr && dstInfo != nullptr) &&
158         !WindowHelper::CheckSupportWindowMode(dstNode->GetWindowMode(), dstNode->GetWindowModeSupportType(), dstInfo)) {
159         WLOGFE("RSWindowAnimation: the mode of dstNode isn't supported, winId: %{public}u, mode: %{public}u, "
160             "windowModeSupportType: %{public}u", dstNode->GetWindowId(), dstNode->GetWindowMode(),
161             dstNode->GetWindowModeSupportType());
162         return false;
163     }
164 
165     auto node = (dstNode != nullptr ? dstNode : srcNode);
166     return CheckRemoteAnimationEnabled(node->GetDisplayId());
167 }
168 
OnRemoteDie(const sptr<IRemoteObject> & remoteObject)169 void RemoteAnimation::OnRemoteDie(const sptr<IRemoteObject>& remoteObject)
170 {
171     WLOGFI("RSWindowAnimation: OnRemoteDie!");
172     if (windowAnimationController_ != nullptr && windowAnimationController_->AsObject() == remoteObject) {
173         windowAnimationController_ = nullptr;
174     }
175     if (animationFirst_) {
176         CallbackTimeOutProcess();
177     }
178 }
179 
GetAndDrawSnapShot(const sptr<WindowNode> & srcNode)180 static void GetAndDrawSnapShot(const sptr<WindowNode>& srcNode)
181 {
182     if (srcNode == nullptr || srcNode->leashWinSurfaceNode_ == nullptr) {
183         TLOGD(WmsLogTag::WMS_STARTUP_PAGE, "srcNode or srcNode->leashWinSurfaceNode_ is empty");
184         return;
185     }
186     if (srcNode->firstFrameAvailable_) {
187         std::shared_ptr<Media::PixelMap> pixelMap;
188         bool snapSucc = SurfaceDraw::GetSurfaceSnapshot(srcNode->surfaceNode_, pixelMap, SNAPSHOT_TIMEOUT_MS, 1.0, 1.0);
189         if (!snapSucc) {
190             // need to draw starting window when get pixelmap failed
191             TLOGE(WmsLogTag::WMS_STARTUP_PAGE, "get surfaceSnapshot failed for window:%{public}u",
192                 srcNode->GetWindowId());
193             return;
194         }
195         WindowInnerManager::GetInstance().UpdateMissionSnapShot(srcNode, pixelMap);
196         struct RSSurfaceNodeConfig rsSurfaceNodeConfig;
197         rsSurfaceNodeConfig.SurfaceNodeName = "closeWin" + std::to_string(srcNode->GetWindowId());
198         srcNode->closeWinSurfaceNode_ = RSSurfaceNode::Create(rsSurfaceNodeConfig,
199             RSSurfaceNodeType::STARTING_WINDOW_NODE);
200         auto rect = srcNode->GetWindowRect();
201         srcNode->closeWinSurfaceNode_->SetBounds(0, 0, rect.width_, rect.height_);
202         SurfaceDraw::DrawImageRect(srcNode->closeWinSurfaceNode_, srcNode->GetWindowRect(),
203             pixelMap, 0x00ffffff, true);
204         srcNode->leashWinSurfaceNode_->RemoveChild(srcNode->surfaceNode_);
205         srcNode->leashWinSurfaceNode_->AddChild(srcNode->closeWinSurfaceNode_, -1);
206         RSTransaction::FlushImplicitTransaction();
207         TLOGI(WmsLogTag::WMS_STARTUP_PAGE, "Draw surface snapshot in starting window for window:%{public}u",
208             srcNode->GetWindowId());
209     } else if (srcNode->surfaceNode_) {
210         srcNode->surfaceNode_->SetIsNotifyUIBufferAvailable(true);
211         TLOGI(WmsLogTag::WMS_STARTUP_PAGE, "Draw startingWindow in starting window for window:%{public}u",
212             srcNode->GetWindowId());
213     }
214 }
215 
GetTransitionEvent(sptr<WindowTransitionInfo> srcInfo,sptr<WindowTransitionInfo> dstInfo,const sptr<WindowNode> & srcNode,const sptr<WindowNode> & dstNode)216 TransitionEvent RemoteAnimation::GetTransitionEvent(sptr<WindowTransitionInfo> srcInfo,
217     sptr<WindowTransitionInfo> dstInfo, const sptr<WindowNode>& srcNode, const sptr<WindowNode>& dstNode)
218 {
219     auto transitionReason = srcInfo->GetTransitionReason(); // src reason same as dst reason
220     if (srcNode != nullptr && eventMap_.find(transitionReason) != eventMap_.end()) {
221         WLOGFI("current window:%{public}u state: %{public}u transitionReason:%{public}u", srcNode->GetWindowId(),
222             static_cast<uint32_t>(srcNode->stateMachine_.GetCurrentState()), static_cast<uint32_t>(transitionReason));
223         if (srcNode->stateMachine_.IsWindowNodeHiddenOrHiding()) {
224             WLOGFE("srcNode is hiding or hidden id: %{public}u!", srcNode->GetWindowId());
225             return TransitionEvent::UNKNOWN;
226         }
227         return eventMap_[transitionReason];
228     }
229     WLOGFI("Ability Transition");
230     if (dstNode == nullptr) {
231         if (dstInfo->GetAbilityToken() == nullptr) {
232             WLOGFE("target window abilityToken is null");
233         }
234         return TransitionEvent::UNKNOWN;
235     } else {
236         WLOGFI("current window:%{public}u state: %{public}u", dstNode->GetWindowId(),
237             static_cast<uint32_t>(dstNode->stateMachine_.GetCurrentState()));
238         if (WindowHelper::IsMainWindow(dstInfo->GetWindowType())) {
239             if (dstNode->stateMachine_.IsWindowNodeShownOrShowing()) {
240                 WLOGFE("dstNode is showing or shown id: %{public}d state:%{public}u!",
241                     dstNode->GetWindowId(), static_cast<uint32_t>(dstNode->stateMachine_.GetCurrentState()));
242                 return TransitionEvent::UNKNOWN;
243             }
244             return TransitionEvent::APP_TRANSITION;
245         } else if (dstInfo->GetWindowType() == WindowType::WINDOW_TYPE_DESKTOP) {
246             return TransitionEvent::HOME;
247         }
248     }
249     return TransitionEvent::UNKNOWN;
250 }
251 
GetTransitionFinishedCallback(const sptr<WindowNode> & srcNode,const sptr<WindowNode> & dstNode)252 sptr<RSWindowAnimationFinishedCallback> RemoteAnimation::GetTransitionFinishedCallback(
253     const sptr<WindowNode>& srcNode, const sptr<WindowNode>& dstNode)
254 {
255     wptr<WindowNode> weak = dstNode;
256     wptr<WindowNode> weakSrc = srcNode;
257     auto callback = [weakSrc, weak]() {
258         WLOGFI("RSWindowAnimation: on finish transition with minimize pre fullscreen!");
259         auto weakNode = weak.promote();
260         if (weakNode == nullptr) {
261             WLOGFE("dst windowNode is nullptr!");
262             return;
263         }
264         FinishAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast<int32_t>(TraceTaskId::REMOTE_ANIMATION),
265             "wms:async:ShowRemoteAnimation");
266         if (!weakNode->stateMachine_.IsWindowNodeShownOrShowing()) {
267             WLOGFI("node:%{public}u is not play show animation with state:%{public}u!", weakNode->GetWindowId(),
268                 static_cast<uint32_t>(weakNode->stateMachine_.GetCurrentState()));
269             return;
270         }
271         MinimizeApp::ExecuteMinimizeAll(); // minimize execute in show animation
272         RSAnimationTimingProtocol timingProtocol(200); // animation time
273         RSNode::Animate(timingProtocol, RSAnimationTimingCurve::EASE_OUT, [weakNode]() {
274             auto winRect = weakNode->GetWindowRect();
275             WLOGFD("name:%{public}s id:%{public}u winRect:[x:%{public}d, y:%{public}d, w:%{public}d, h:%{public}d]",
276                 weakNode->GetWindowName().c_str(), weakNode->GetWindowId(),
277                 winRect.posX_, winRect.posY_, winRect.width_, winRect.height_);
278             if (!weakNode->leashWinSurfaceNode_) {
279                 return;
280             }
281             weakNode->leashWinSurfaceNode_->SetBounds(
282                 winRect.posX_, winRect.posY_, winRect.width_, winRect.height_);
283             RSTransaction::FlushImplicitTransaction();
284             weakNode->stateMachine_.TransitionTo(WindowNodeState::SHOW_ANIMATION_DONE);
285         });
286     };
287     return CreateAnimationFinishedCallback(callback, dstNode);
288 }
289 
NotifyAnimationStartApp(sptr<WindowTransitionInfo> srcInfo,const sptr<WindowNode> & srcNode,const sptr<WindowNode> & dstNode,sptr<RSWindowAnimationTarget> & dstTarget,sptr<RSWindowAnimationFinishedCallback> & finishedCallback)290 WMError RemoteAnimation::NotifyAnimationStartApp(sptr<WindowTransitionInfo> srcInfo,
291     const sptr<WindowNode>& srcNode, const sptr<WindowNode>& dstNode,
292     sptr<RSWindowAnimationTarget>& dstTarget, sptr<RSWindowAnimationFinishedCallback>& finishedCallback)
293 {
294     if (animationFirst_) {
295         // From Recent also need to minimize window
296         MinimizeApp::ExecuteMinimizeAll();
297     }
298     // start app from launcher
299     if (srcNode != nullptr && srcNode->GetWindowType() == WindowType::WINDOW_TYPE_DESKTOP) {
300         WLOGFI("RSWindowAnimation: start app id:%{public}u from launcher!", dstNode->GetWindowId());
301         windowAnimationController_->OnStartApp(StartingAppType::FROM_LAUNCHER, dstTarget, finishedCallback);
302         return WMError::WM_OK;
303     }
304     // start app from recent
305     if (srcInfo != nullptr && srcInfo->GetIsRecent()) {
306         WLOGFI("RSWindowAnimation: start app id:%{public}u from recent!", dstNode->GetWindowId());
307         windowAnimationController_->OnStartApp(StartingAppType::FROM_RECENT, dstTarget, finishedCallback);
308         return WMError::WM_OK;
309     }
310     // start app from other
311     WLOGFI("RSWindowAnimation: start app id:%{public}u from other!", dstNode->GetWindowId());
312     windowAnimationController_->OnStartApp(StartingAppType::FROM_OTHER, dstTarget, finishedCallback);
313     return WMError::WM_OK;
314 }
315 
GetExpectRect(const sptr<WindowNode> & dstNode,const sptr<RSWindowAnimationTarget> & dstTarget)316 void RemoteAnimation::GetExpectRect(const sptr<WindowNode>& dstNode, const sptr<RSWindowAnimationTarget>& dstTarget)
317 {
318     // when exit immersive, startingWindow (0,0,w,h), but app need avoid
319     bool needAvoid = (dstNode->GetWindowFlags() & static_cast<uint32_t>(WindowFlag::WINDOW_FLAG_NEED_AVOID));
320     auto winRoot = windowRoot_.promote();
321     if (needAvoid && winRoot) {
322         auto avoidRect = winRoot->GetDisplayRectWithoutSystemBarAreas(dstNode);
323         if (WindowHelper::IsEmptyRect(avoidRect)) {
324             return;
325         }
326         WLOGFI("name:%{public}s id:%{public}u avoidRect:[x:%{public}d, y:%{public}d, w:%{public}d, h:%{public}d]",
327             dstNode->GetWindowName().c_str(), dstNode->GetWindowId(),
328             avoidRect.posX_, avoidRect.posY_, avoidRect.width_, avoidRect.height_);
329         if (WindowHelper::IsMainFullScreenWindow(dstNode->GetWindowType(), dstNode->GetWindowMode())) {
330             auto boundsRect = RectF(avoidRect.posX_, avoidRect.posY_, avoidRect.width_, avoidRect.height_);
331             auto displayInfo = DisplayGroupInfo::GetInstance().GetDisplayInfo(dstNode->GetDisplayId());
332             if (displayInfo && WmsUtils::IsExpectedRotatableWindow(dstNode->GetRequestedOrientation(),
333                 displayInfo->GetDisplayOrientation(), dstNode->GetWindowFlags())) {
334                 WLOGFD("[FixOrientation] window %{public}u expected rotatable, pre-cal bounds", dstNode->GetWindowId());
335                 boundsRect = RectF(avoidRect.posX_, avoidRect.posY_, avoidRect.height_, avoidRect.width_);
336             }
337             dstTarget->windowBounds_.rect_ = boundsRect;
338             if (dstNode->leashWinSurfaceNode_) {
339                 dstNode->leashWinSurfaceNode_->SetBounds(avoidRect.posX_, avoidRect.posY_,
340                     avoidRect.width_, avoidRect.height_);
341             }
342         }
343     }
344 }
345 
NotifyAnimationTransition(sptr<WindowTransitionInfo> srcInfo,sptr<WindowTransitionInfo> dstInfo,const sptr<WindowNode> & srcNode,const sptr<WindowNode> & dstNode)346 WMError RemoteAnimation::NotifyAnimationTransition(sptr<WindowTransitionInfo> srcInfo,
347     sptr<WindowTransitionInfo> dstInfo, const sptr<WindowNode>& srcNode,
348     const sptr<WindowNode>& dstNode)
349 {
350     if (!dstNode) {
351         return WMError::WM_ERROR_NULLPTR;
352     }
353     WLOGFI("RSWindowAnimation: notify animation transition with dst currId:%{public}u!", dstNode->GetWindowId());
354     bool needMinimizeSrcNode = MinimizeApp::IsNodeNeedMinimizeWithReason(srcNode, MinimizeReason::OTHER_WINDOW);
355     auto finishedCallback = CreateShowAnimationFinishedCallback(srcNode, dstNode, needMinimizeSrcNode);
356     if (finishedCallback == nullptr) {
357         return WMError::WM_ERROR_NO_MEM;
358     }
359     auto dstTarget = CreateWindowAnimationTarget(dstInfo, dstNode);
360     if (dstTarget == nullptr) {
361         WLOGFE("RSWindowAnimation: Failed to create dst target!");
362         finishedCallback->OnAnimationFinished();
363         return WMError::WM_ERROR_NO_MEM;
364     }
365 
366     std::unordered_map<std::string, std::string> payload;
367     if (srcNode) {
368         payload["srcPid"] = std::to_string(srcNode->GetCallingPid());
369     }
370     ResSchedReport::GetInstance().ResSchedDataReport(
371         Rosen::RES_TYPE_SHOW_REMOTE_ANIMATION, Rosen::REMOTE_ANIMATION_BEGIN, payload);
372     // when exit immersive, startingWindow (0,0,w,h), but app need avoid
373     GetExpectRect(dstNode, dstTarget);
374     dstNode->isPlayAnimationShow_ = true;
375     // Transition to next state and update task count will success when enable animationFirst_
376     dstNode->stateMachine_.TransitionTo(WindowNodeState::SHOW_ANIMATION_PLAYING);
377     dstNode->stateMachine_.UpdateAnimationTaskCount(true);
378     // from app to app
379     if (needMinimizeSrcNode && srcNode != nullptr) {
380         auto srcTarget = CreateWindowAnimationTarget(srcInfo, srcNode);
381         // to avoid normal animation
382         srcNode->isPlayAnimationHide_ = true;
383         srcNode->stateMachine_.TransitionTo(WindowNodeState::HIDE_ANIMATION_PLAYING);
384         srcNode->stateMachine_.UpdateAnimationTaskCount(true);
385         auto winController = windowController_.promote();
386         if (winController) {
387             winController->RemoveWindowNode(srcNode->GetWindowId(), true);
388         }
389         if (animationFirst_) {
390             // Notify minimize before animation when animationFirst is enable.
391             // Or notify minimize in animation finished callback.
392             MinimizeApp::ExecuteMinimizeAll();
393         }
394         WLOGFI("RSWindowAnimation: app transition from id:%{public}u to id:%{public}u!",
395             srcNode->GetWindowId(), dstNode->GetWindowId());
396         windowAnimationController_->OnAppTransition(srcTarget, dstTarget, finishedCallback);
397         return WMError::WM_OK;
398     }
399     return NotifyAnimationStartApp(srcInfo, srcNode, dstNode, dstTarget, finishedCallback);
400 }
401 
NotifyAnimationMinimize(sptr<WindowTransitionInfo> srcInfo,const sptr<WindowNode> & srcNode)402 WMError RemoteAnimation::NotifyAnimationMinimize(sptr<WindowTransitionInfo> srcInfo, const sptr<WindowNode>& srcNode)
403 {
404     sptr<RSWindowAnimationTarget> srcTarget = CreateWindowAnimationTarget(srcInfo, srcNode);
405     if (srcTarget == nullptr) {
406         return WMError::WM_ERROR_NO_MEM;
407     }
408     WLOGFI("RSWindowAnimation: notify animation minimize Id:%{public}u!", srcNode->GetWindowId());
409     srcNode->isPlayAnimationHide_ = true;
410     srcNode->stateMachine_.TransitionTo(WindowNodeState::HIDE_ANIMATION_PLAYING);
411     auto winController = windowController_.promote();
412     if (winController) {
413         winController->RemoveWindowNode(srcNode->GetWindowId(), true);
414     }
415     sptr<RSWindowAnimationFinishedCallback> finishedCallback = CreateHideAnimationFinishedCallback(
416         srcNode, TransitionEvent::MINIMIZE);
417     if (finishedCallback == nullptr) {
418         WLOGFE("New RSIWindowAnimationFinishedCallback failed");
419         return WMError::WM_ERROR_NO_MEM;
420     }
421 
422     srcNode->stateMachine_.TransitionTo(WindowNodeState::HIDE_ANIMATION_PLAYING);
423     srcNode->stateMachine_.UpdateAnimationTaskCount(true);
424     windowAnimationController_->OnMinimizeWindow(srcTarget, finishedCallback);
425     return WMError::WM_OK;
426 }
427 
NotifyAnimationClose(sptr<WindowTransitionInfo> srcInfo,const sptr<WindowNode> & srcNode,TransitionEvent event)428 WMError RemoteAnimation::NotifyAnimationClose(sptr<WindowTransitionInfo> srcInfo, const sptr<WindowNode>& srcNode,
429     TransitionEvent event)
430 {
431     sptr<RSWindowAnimationTarget> srcTarget = CreateWindowAnimationTarget(srcInfo, srcNode);
432     if (srcTarget == nullptr) {
433         return WMError::WM_ERROR_NO_MEM;
434     }
435     WLOGFI("RSWindowAnimation: notify animation close id:%{public}u!", srcNode->GetWindowId());
436     srcNode->isPlayAnimationHide_ = true;
437     auto winController = windowController_.promote();
438     if (winController) {
439         winController->RemoveWindowNode(srcNode->GetWindowId(), true);
440     }
441     sptr<RSWindowAnimationFinishedCallback> finishedCallback = CreateHideAnimationFinishedCallback(srcNode, event);
442     if (finishedCallback == nullptr) {
443         WLOGFE("New RSIWindowAnimationFinishedCallback failed");
444         return WMError::WM_ERROR_NO_MEM;
445     }
446     srcNode->stateMachine_.TransitionTo(WindowNodeState::HIDE_ANIMATION_PLAYING);
447     srcNode->stateMachine_.UpdateAnimationTaskCount(true);
448     windowAnimationController_->OnCloseWindow(srcTarget, finishedCallback);
449     return WMError::WM_OK;
450 }
451 
NotifyAnimationAbilityDied(sptr<WindowTransitionInfo> info)452 void RemoteAnimation::NotifyAnimationAbilityDied(sptr<WindowTransitionInfo> info)
453 {
454     if (info == nullptr) {
455         WLOGFE("Window transition info is null!");
456         return;
457     }
458     auto handler = wmsTaskHandler_.lock();
459     if (handler == nullptr) {
460         WLOGFE("wmsTaskHandler_ is nullptr");
461         return;
462     }
463     // need post task when visit windowRoot node map
464     auto task = [info]() {
465         if (!CheckAnimationController()) {
466             return;
467         }
468         WLOGFI("ability died bundleName:%{public}s, abilityName:%{public}s", info->GetBundleName().c_str(),
469             info->GetAbilityName().c_str());
470         sptr<RSWindowAnimationTarget> target = new(std::nothrow) RSWindowAnimationTarget();
471         if (target == nullptr) {
472             WLOGFE("target is nullptr");
473             return;
474         }
475         target->bundleName_ = info->GetBundleName();
476         target->abilityName_ = info->GetAbilityName();
477         target->missionId_ = info->GetMissionId();
478         target->windowId_ = INVALID_WINDOW_ID;
479         auto func = []() { WLOGFI("NotifyAbilityDied finished!"); };
480         auto finishCallback = CreateAnimationFinishedCallback(func, nullptr);
481         windowAnimationController_->OnCloseWindow(target, finishCallback);
482     };
483     bool ret = handler->PostTask(task, "wms:NotifyAnimationAbilityDied",
484         0, AppExecFwk::EventQueue::Priority::IMMEDIATE);
485     if (!ret) {
486         WLOGFE("EventHandler PostTask Failed");
487         task();
488     }
489 }
490 
NotifyAnimationBackTransition(sptr<WindowTransitionInfo> srcInfo,sptr<WindowTransitionInfo> dstInfo,const sptr<WindowNode> & srcNode,const sptr<WindowNode> & dstNode,const TransitionEvent event)491 WMError RemoteAnimation::NotifyAnimationBackTransition(sptr<WindowTransitionInfo> srcInfo,
492     sptr<WindowTransitionInfo> dstInfo, const sptr<WindowNode>& srcNode,
493     const sptr<WindowNode>& dstNode, const TransitionEvent event)
494 {
495     if (!animationFirst_) {
496         WLOGFE("not animation first!");
497         return WMError::WM_ERROR_NO_REMOTE_ANIMATION;
498     }
499     if (!dstNode || !srcNode) {
500         WLOGFE("dstNode or srcNode is nullptr, no need transition animation");
501         return WMError::WM_ERROR_NULLPTR;
502     }
503     WLOGFI("RSWindowAnimation: app back transition from id:%{public}u to id:%{public}u!",
504         srcNode->GetWindowId(), dstNode->GetWindowId());
505     sptr<RSWindowAnimationTarget> srcTarget = CreateWindowAnimationTarget(srcInfo, srcNode);
506     sptr<RSWindowAnimationTarget> dstTarget = CreateWindowAnimationTarget(dstInfo, dstNode);
507     if (srcTarget == nullptr || dstTarget == nullptr) {
508         return WMError::WM_ERROR_NO_MEM;
509     }
510     srcNode->isPlayAnimationHide_ = true;
511     srcNode->stateMachine_.TransitionTo(WindowNodeState::HIDE_ANIMATION_PLAYING);
512     srcNode->stateMachine_.UpdateAnimationTaskCount(true);
513     auto winController = windowController_.promote();
514     if (winController) {
515         winController->RemoveWindowNode(srcNode->GetWindowId(), true);
516         if (event == TransitionEvent::BACK_TRANSITION) {
517             GetAndDrawSnapShot(srcNode);
518         }
519     }
520     if (animationFirst_ && event == TransitionEvent::BACKGROUND_TRANSITION) {
521         MinimizeApp::ExecuteMinimizeAll();
522     }
523     dstNode->isPlayAnimationShow_ = true;
524     dstNode->stateMachine_.TransitionTo(WindowNodeState::SHOW_ANIMATION_PLAYING);
525     dstNode->stateMachine_.UpdateAnimationTaskCount(true);
526     wptr<WindowNode> srcNodeWptr = srcNode;
527     wptr<WindowNode> dstNodeWptr = dstNode;
528     auto func = [srcNodeWptr, dstNodeWptr]() {
529         WLOGFI("RSWindowAnimation: animationFirst use state machine process AnimationBackTransition!");
530         auto srcNodeSptr = srcNodeWptr.promote();
531         auto dstNodeSptr = dstNodeWptr.promote();
532         ProcessNodeStateTask(srcNodeSptr);
533         ProcessNodeStateTask(dstNodeSptr);
534         FinishAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast<int32_t>(TraceTaskId::REMOTE_ANIMATION),
535             "wms:async:ShowRemoteAnimation");
536     };
537     sptr<RSWindowAnimationFinishedCallback> finishedCallback = CreateAnimationFinishedCallback(func, dstNode);
538     if (finishedCallback == nullptr) {
539         return WMError::WM_ERROR_NO_MEM;
540     }
541     windowAnimationController_->OnAppBackTransition(srcTarget, dstTarget, finishedCallback);
542     return WMError::WM_OK;
543 }
544 
GetAnimationTargetsForHome(std::vector<sptr<RSWindowAnimationTarget>> & animationTargets,std::vector<wptr<WindowNode>> needMinimizeAppNodes)545 void RemoteAnimation::GetAnimationTargetsForHome(std::vector<sptr<RSWindowAnimationTarget>>& animationTargets,
546     std::vector<wptr<WindowNode>> needMinimizeAppNodes)
547 {
548     for (auto& weakNode : needMinimizeAppNodes) {
549         auto srcNode = weakNode.promote();
550         sptr<WindowTransitionInfo> srcInfo = new(std::nothrow) WindowTransitionInfo();
551         sptr<RSWindowAnimationTarget> srcTarget = CreateWindowAnimationTarget(srcInfo, srcNode);
552         if (srcTarget == nullptr) {
553             continue;
554         }
555         WLOGFI("notify animation by home, need minimize id%{public}u", srcNode->GetWindowId());
556         if (!WindowHelper::IsMainWindow(srcNode->GetWindowType()) ||
557             srcNode->stateMachine_.IsWindowNodeHiddenOrHiding()) {
558             WLOGFE("srcNode is already hiding or hidden id: %{public}d!", srcNode->GetWindowId());
559             continue;
560         }
561         StartAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast<int32_t>(TraceTaskId::REMOTE_ANIMATION_HOME),
562             "wms:async:RemoteAnimationHome");
563         srcNode->isPlayAnimationHide_ = true;
564         srcNode->stateMachine_.TransitionTo(WindowNodeState::HIDE_ANIMATION_PLAYING);
565         srcNode->stateMachine_.UpdateAnimationTaskCount(true);
566         auto winController = windowController_.promote();
567         if (winController) {
568             winController->RemoveWindowNode(srcNode->GetWindowId(), true);
569         }
570         animationTargets.emplace_back(srcTarget);
571     }
572 }
573 
GetAnimationHomeFinishCallback(std::function<void (void)> & func,std::vector<wptr<WindowNode>> needMinimizeAppNodes)574 static void GetAnimationHomeFinishCallback(std::function<void(void)>& func,
575     std::vector<wptr<WindowNode>> needMinimizeAppNodes)
576 {
577     func = [needMinimizeAppNodes]() {
578         WLOGFI("NotifyAnimationByHome in animation callback not animationFirst");
579         for (auto& weakNode : needMinimizeAppNodes) {
580             auto srcNode = weakNode.promote();
581             if (srcNode == nullptr || !srcNode->stateMachine_.IsWindowNodeHiddenOrHiding()) {
582                 WLOGFE("windowNode is nullptr or is not play hide animation!");
583                 continue;
584             }
585             srcNode->stateMachine_.TransitionTo(WindowNodeState::HIDE_ANIMATION_DONE);
586         }
587         MinimizeApp::ExecuteMinimizeTargetReasons(MinimizeReason::MINIMIZE_ALL);
588         FinishAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast<int32_t>(TraceTaskId::REMOTE_ANIMATION),
589             "wms:async:ShowRemoteAnimation");
590     };
591 }
592 
NotifyAnimationByHome()593 WMError RemoteAnimation::NotifyAnimationByHome()
594 {
595     if (!CheckAnimationController()) {
596         return WMError::WM_ERROR_NO_REMOTE_ANIMATION;
597     }
598     auto needMinimizeAppNodes = MinimizeApp::GetNeedMinimizeAppNodesWithReason(MinimizeReason::MINIMIZE_ALL);
599     WLOGFI("RSWindowAnimation: notify animation by home, need minimize size: %{public}u",
600         static_cast<uint32_t>(needMinimizeAppNodes.size()));
601     std::vector<sptr<RSWindowAnimationTarget>> animationTargets;
602     GetAnimationTargetsForHome(animationTargets, needMinimizeAppNodes);
603     std::function<void(void)> func;
604     if (animationFirst_) {
605         MinimizeApp::ExecuteMinimizeTargetReasons(MinimizeReason::MINIMIZE_ALL);
606         func = [needMinimizeAppNodes]() {
607             WLOGFI("NotifyAnimationByHome in animation callback in animationFirst with size:%{public}u",
608                 static_cast<uint32_t>(needMinimizeAppNodes.size()));
609             for (auto& weakNode : needMinimizeAppNodes) {
610                 auto srcNode = weakNode.promote();
611                 ProcessNodeStateTask(srcNode);
612                 FinishAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER,
613                     static_cast<int32_t>(TraceTaskId::REMOTE_ANIMATION_HOME),
614                     "wms:async:RemoteAnimationHome");
615             }
616         };
617     } else {
618         GetAnimationHomeFinishCallback(func, needMinimizeAppNodes);
619     }
620 #ifdef SOC_PERF_ENABLE
621     constexpr int32_t ACTION_TYPE_CPU_BOOST_CMDID = 10060;
622     OHOS::SOCPERF::SocPerfClient::GetInstance().PerfRequestEx(ACTION_TYPE_CPU_BOOST_CMDID, true, "");
623 #endif
624     sptr<RSWindowAnimationFinishedCallback> finishedCallback = CreateAnimationFinishedCallback(func, nullptr);
625     if (finishedCallback == nullptr) {
626         return WMError::WM_ERROR_NO_MEM;
627     }
628     // need use OnMinimizeWindows with controller
629     windowAnimationController_->OnMinimizeAllWindow(animationTargets, finishedCallback);
630     return WMError::WM_OK;
631 }
632 
NotifyAnimationTargetsUpdate(std::vector<uint32_t> & fullScreenWinIds,std::vector<uint32_t> & floatWinIds)633 void RemoteAnimation::NotifyAnimationTargetsUpdate(std::vector<uint32_t>& fullScreenWinIds,
634     std::vector<uint32_t>& floatWinIds)
635 {
636     auto handler = wmsTaskHandler_.lock();
637     if (handler == nullptr) {
638         WLOGFE("wmsTaskHandler_ is nullptr");
639         return;
640     }
641     // need post task when visit windowRoot node map
642     auto task = [fullScreenWinIds, floatWinIds]() {
643         if (!CheckAnimationController()) {
644             return;
645         }
646         auto winRoot = windowRoot_.promote();
647         if (winRoot == nullptr) {
648             WLOGFE("window root is nullptr");
649             return;
650         }
651         std::vector<sptr<RSWindowAnimationTarget>> floatAnimationTargets;
652         std::vector<sptr<RSWindowAnimationTarget>> fullScreenAnimationTargets;
653         for (auto& id : fullScreenWinIds) {
654             auto fullScreenNode = winRoot->GetWindowNode(id);
655             sptr<RSWindowAnimationTarget> fullScreenTarget = CreateWindowAnimationTarget(nullptr, fullScreenNode);
656             if (fullScreenTarget != nullptr) {
657                 fullScreenAnimationTargets.emplace_back(fullScreenTarget);
658             }
659         }
660         for (auto& id : floatWinIds) {
661             auto floatNode = winRoot->GetWindowNode(id);
662             sptr<RSWindowAnimationTarget> floatTarget = CreateWindowAnimationTarget(nullptr, floatNode);
663             if (floatTarget != nullptr) {
664                 floatAnimationTargets.emplace_back(floatTarget);
665             }
666         }
667         // delete when need all fullscreen targets
668         sptr<RSWindowAnimationTarget> fullScreenAnimationTarget = nullptr;
669         if (!fullScreenAnimationTargets.empty()) {
670             fullScreenAnimationTarget = fullScreenAnimationTargets[0];
671         }
672         windowAnimationController_->OnWindowAnimationTargetsUpdate(fullScreenAnimationTarget,
673             floatAnimationTargets);
674     };
675     bool ret = handler->PostTask(task, "wms:NotifyAnimationTargetsUpdate", 0,
676         AppExecFwk::EventQueue::Priority::IMMEDIATE);
677     if (!ret) {
678         WLOGFE("EventHandler PostTask Failed");
679         task();
680     }
681 }
682 
NotifyAnimationScreenUnlock(std::function<void (void)> callback,sptr<WindowNode> node)683 WMError RemoteAnimation::NotifyAnimationScreenUnlock(std::function<void(void)> callback, sptr<WindowNode> node)
684 {
685     if (!CheckAnimationController()) {
686         return WMError::WM_ERROR_NO_REMOTE_ANIMATION;
687     }
688     WLOGFI("NotifyAnimationScreenUnlock");
689     sptr<RSWindowAnimationFinishedCallback> finishedCallback = CreateAnimationFinishedCallback(callback, node);
690     if (finishedCallback == nullptr) {
691         return WMError::WM_ERROR_NO_MEM;
692     }
693 
694     windowAnimationController_->OnScreenUnlock(finishedCallback);
695     return WMError::WM_OK;
696 }
697 
GetWindowAnimationTargets(std::vector<uint32_t> missionIds,std::vector<sptr<RSWindowAnimationTarget>> & targets)698 WMError RemoteAnimation::GetWindowAnimationTargets(std::vector<uint32_t> missionIds,
699     std::vector<sptr<RSWindowAnimationTarget>>& targets)
700 {
701     auto winRoot = windowRoot_.promote();
702     if (winRoot == nullptr) {
703         WLOGFE("window root is nullptr");
704         return WMError::WM_ERROR_NO_MEM;
705     }
706     for (uint32_t& missionId : missionIds) {
707         sptr<WindowNode> windowNode = winRoot->GetWindowNodeByMissionId(missionId);
708         auto target = CreateWindowAnimationTarget(nullptr, windowNode);
709         if (target == nullptr) {
710             continue;
711         }
712         targets.push_back(target);
713     }
714     return WMError::WM_OK;
715 }
716 
CreateWindowAnimationTarget(sptr<WindowTransitionInfo> info,const sptr<WindowNode> & windowNode)717 sptr<RSWindowAnimationTarget> RemoteAnimation::CreateWindowAnimationTarget(sptr<WindowTransitionInfo> info,
718     const sptr<WindowNode>& windowNode)
719 {
720     if (windowNode == nullptr) {
721         WLOGFW("Failed to create window animation target, window node is null!");
722         return nullptr;
723     }
724 
725     sptr<RSWindowAnimationTarget> windowAnimationTarget = new(std::nothrow) RSWindowAnimationTarget();
726     if (windowAnimationTarget == nullptr) {
727         WLOGFE("New RSWindowAnimationTarget failed");
728         return nullptr;
729     }
730 
731     if (WindowHelper::IsMainWindow(windowNode->GetWindowType())) { // only starting window has abilityInfo
732         windowAnimationTarget->bundleName_ = windowNode->abilityInfo_.bundleName_;
733         windowAnimationTarget->abilityName_ = windowNode->abilityInfo_.abilityName_;
734     } else if (info) { // use for back, minimize, close
735         windowAnimationTarget->bundleName_ = info->GetBundleName();
736         windowAnimationTarget->abilityName_ = info->GetAbilityName();
737     }
738 
739     windowAnimationTarget->missionId_ = windowNode->abilityInfo_.missionId_;
740     windowAnimationTarget->windowId_ = windowNode->GetWindowId();
741     windowAnimationTarget->displayId_ = windowNode->GetDisplayId();
742     // some ability not has startingWindow,e.g. oobe
743     if (WindowHelper::IsAppWindow(windowNode->GetWindowType()) && windowNode->leashWinSurfaceNode_) {
744         windowAnimationTarget->surfaceNode_ = windowNode->leashWinSurfaceNode_;
745     } else {
746         windowAnimationTarget->surfaceNode_ = windowNode->surfaceNode_;
747     }
748     if (windowAnimationTarget->surfaceNode_ == nullptr) {
749         WLOGFE("Window surface node is null id:%{public}u, type:%{public}u!",
750             windowNode->GetWindowId(), windowNode->GetWindowType());
751         return nullptr;
752     }
753 
754     auto rect = windowNode->GetWindowRect();
755     // 0, 1, 2, 3: convert bounds to RectF
756     auto boundsRect = RectF(rect.posX_, rect.posY_, rect.width_, rect.height_);
757     auto displayInfo = DisplayGroupInfo::GetInstance().GetDisplayInfo(windowNode->GetDisplayId());
758     if (displayInfo && WmsUtils::IsExpectedRotatableWindow(windowNode->GetRequestedOrientation(),
759         displayInfo->GetDisplayOrientation(), windowNode->GetWindowMode(), windowNode->GetWindowFlags())) {
760         WLOGFD("[FixOrientation] the window %{public}u is expected rotatable, pre-calculate bounds, rect:"
761             " [%{public}d, %{public}d, %{public}d, %{public}d]", windowNode->GetWindowId(), rect.posX_, rect.posY_,
762             rect.height_, rect.width_);
763         boundsRect = RectF(rect.posX_, rect.posY_, rect.height_, rect.width_);
764     }
765     auto& stagingProperties = windowAnimationTarget->surfaceNode_->GetStagingProperties();
766     auto radius = stagingProperties.GetCornerRadius();
767     windowAnimationTarget->windowBounds_ = RRect(boundsRect, radius);
768     return windowAnimationTarget;
769 }
770 
PostProcessShowCallback(const sptr<WindowNode> & node)771 void RemoteAnimation::PostProcessShowCallback(const sptr<WindowNode>& node)
772 {
773     if (node == nullptr) {
774         WLOGFD("windowNode is nullptr!");
775         return;
776     }
777     auto winRect = node->GetWindowRect();
778     if (!node->leashWinSurfaceNode_) {
779         WLOGFD("leashWinSurfaceNode_ is nullptr with id: %{public}u!", node->GetWindowId());
780         return;
781     }
782     WLOGFD("name:%{public}s id:%{public}u winRect:[x:%{public}d, y:%{public}d, w:%{public}d, h:%{public}d]",
783         node->GetWindowName().c_str(), node->GetWindowId(),
784         winRect.posX_, winRect.posY_, winRect.width_, winRect.height_);
785     node->leashWinSurfaceNode_->SetBounds(
786         winRect.posX_, winRect.posY_, winRect.width_, winRect.height_);
787     if (WindowHelper::IsRotatableWindow(node->GetWindowType(), node->GetWindowMode())) {
788         auto displayId = node->GetDisplayId();
789         auto requestOri = node->GetRequestedOrientation();
790         WLOGFD("[FixOrientation] show animation finished, update display orientation");
791         if (FIX_ORIENTATION_ENABLE) {
792             DisplayManagerServiceInner::GetInstance().SetOrientationFromWindow(displayId, requestOri, false);
793         } else {
794             DisplayManagerServiceInner::GetInstance().SetOrientationFromWindow(displayId, requestOri, true);
795         }
796     }
797     RSTransaction::FlushImplicitTransaction();
798 }
799 
ExecuteFinalStateTask(sptr<WindowNode> & node)800 void RemoteAnimation::ExecuteFinalStateTask(sptr<WindowNode>& node)
801 {
802     StateTask destroyTask = nullptr;
803     auto winRoot = windowRoot_.promote();
804     if (winRoot == nullptr || node == nullptr) {
805         WLOGFE("windowRoot or node is nullptr");
806         return;
807     }
808     if (node->stateMachine_.IsWindowNodeHiddenOrHiding()) {
809         WLOGFI("execute task removing from rs tree id:%{public}u!", node->GetWindowId());
810         winRoot->UpdateRsTree(node->GetWindowId(), false);
811     } else if (node->stateMachine_.IsWindowNodeShownOrShowing()) {
812         WLOGFI("execute task layout after show animation id:%{public}u!", node->GetWindowId());
813         winRoot->LayoutWhenAddWindowNode(node, true);
814         WindowSystemEffect::SetWindowEffect(node, false); // no need to check animationPlaying in finishCallback
815         auto winController = windowController_.promote();
816         if (winController) {
817             winController->FlushWindowInfo(node->GetWindowId());
818         }
819     } else {
820         WLOGFD("current State:%{public}u invalid", static_cast<uint32_t>(node->stateMachine_.GetCurrentState()));
821     }
822 
823     if (node->stateMachine_.GetDestroyTask(destroyTask)) {
824         destroyTask();
825     }
826 }
827 
CallbackTimeOutProcess()828 void RemoteAnimation::CallbackTimeOutProcess()
829 {
830     auto winRoot = windowRoot_.promote();
831     if (winRoot == nullptr) {
832         WLOGFE("windowRoot is nullptr");
833         return;
834     }
835     std::vector<wptr<WindowNode>> animationPlayingNodes;
836     winRoot->GetAllAnimationPlayingNodes(animationPlayingNodes);
837     WLOGFI("CallbackTimeOutProcess playingNodes:%{public}u", static_cast<uint32_t>(animationPlayingNodes.size()));
838     for (auto& weakNode : animationPlayingNodes) {
839         auto node = weakNode.promote();
840         if (node == nullptr) {
841             continue;
842         }
843         WLOGFI("callback timeout process windowId:%{public}u", node->GetWindowId());
844         node->stateMachine_.ResetAnimationTaskCount(1);
845         ProcessNodeStateTask(node);
846     }
847 }
848 
ReportWindowAnimationAbnormalInfo(sptr<WindowNode> & node)849 static void ReportWindowAnimationAbnormalInfo(sptr<WindowNode>& node)
850 {
851     std::ostringstream oss;
852     oss << "animation callback more than task: " << "window_name: " << node->GetWindowName() << ";";
853     std::string info = oss.str();
854     info += node->stateMachine_.GenStateMachineInfo();
855     int32_t ret = HiSysEventWrite(
856         OHOS::HiviewDFX::HiSysEvent::Domain::WINDOW_MANAGER,
857         "WINDOW_ANIMATION_ABNORMAL",
858         OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
859         "PID", node->GetCallingPid(),
860         "UID", node->GetCallingUid(),
861         "PACKAGE_NAME", node->abilityInfo_.abilityName_,
862         "PROCESS_NAME", node->abilityInfo_.bundleName_,
863         "MSG", info);
864     if (ret != 0) {
865         WLOGFE("Write HiSysEvent error, ret:%{public}d", ret);
866     }
867 }
868 
ProcessNodeStateTask(sptr<WindowNode> & node)869 void RemoteAnimation::ProcessNodeStateTask(sptr<WindowNode>& node)
870 {
871     // when callback come, node maybe destroyed
872     if (node == nullptr) {
873         WLOGFI("node is nullptr!");
874         return;
875     }
876     int32_t taskCount = node->stateMachine_.GetAnimationCount();
877     if (taskCount <= 0) { // no animation task but finishCallback come
878         WLOGFE("ProcessNodeStateTask failed with windowId: %{public}u, name:%{public}s taskCount:%{public}d",
879             node->GetWindowId(), node->GetWindowName().c_str(), taskCount);
880         ReportWindowAnimationAbnormalInfo(node);
881         return;
882     }
883     node->stateMachine_.UpdateAnimationTaskCount(false);
884     taskCount = node->stateMachine_.GetAnimationCount();
885     WLOGFI("ProcessNodeStateTask windowId: %{public}u, name:%{public}s state: %{public}u, taskCount:%{public}d",
886         node->GetWindowId(), node->GetWindowName().c_str(),
887         static_cast<uint32_t>(node->stateMachine_.GetCurrentState()), taskCount);
888     if (taskCount > 0 || taskCount < 0) {
889         WLOGFI("not last state task of window: %{public}d, %{public}d callback left not be executed!",
890             node->GetWindowId(), taskCount);
891         return;
892     }
893     ExecuteFinalStateTask(node);
894     if (node->stateMachine_.IsWindowNodeShownOrShowing()) {
895         // delete when immersive solution change
896         PostProcessShowCallback(node);
897         node->stateMachine_.TransitionTo(WindowNodeState::SHOW_ANIMATION_DONE);
898     } else if (node->stateMachine_.IsWindowNodeHiddenOrHiding()) {
899         node->stateMachine_.TransitionTo(WindowNodeState::HIDE_ANIMATION_DONE);
900         auto winRoot = windowRoot_.promote();
901         if (winRoot != nullptr) {
902             winRoot->UpdateDisplayOrientationWhenHideWindow(node);
903         }
904     } else if (node->stateMachine_.GetCurrentState() == WindowNodeState::DESTROYED) {
905         auto winRoot = windowRoot_.promote();
906         if (winRoot != nullptr) {
907             winRoot->UpdateDisplayOrientationWhenHideWindow(node);
908         }
909     }
910 }
911 
CreateShowAnimationFinishedCallback(const sptr<WindowNode> & srcNode,const sptr<WindowNode> & dstNode,bool needMinimizeSrcNode)912 sptr<RSWindowAnimationFinishedCallback> RemoteAnimation::CreateShowAnimationFinishedCallback(
913     const sptr<WindowNode>& srcNode, const sptr<WindowNode>& dstNode, bool needMinimizeSrcNode)
914 {
915     wptr<WindowNode> srcNodeWptr = srcNode;
916     wptr<WindowNode> dstNodeWptr = dstNode;
917     // need add timeout check
918     std::function<void(void)> func;
919     if (!animationFirst_) {
920         WLOGFI("RSWindowAnimation: not animationFirst use default callback!");
921         return GetTransitionFinishedCallback(srcNode, dstNode);
922     } else {
923         func = [srcNodeWptr, dstNodeWptr, needMinimizeSrcNode]() {
924             WLOGFI("RSWindowAnimation: animationFirst use state machine process ShowAnimationFinishedCallback!");
925             auto srcNodeSptr = srcNodeWptr.promote();
926             auto dstNodeSptr = dstNodeWptr.promote();
927             if (dstNodeSptr == nullptr) {
928                 WLOGFE("dstNode is nullptr!");
929                 return;
930             }
931             ProcessNodeStateTask(dstNodeSptr);
932             // launcher not do this
933             if (needMinimizeSrcNode) {
934                 ProcessNodeStateTask(srcNodeSptr);
935             }
936             if (dstNodeSptr->stateMachine_.GetCurrentState() == WindowNodeState::SHOW_ANIMATION_DONE &&
937                 dstNodeSptr->leashWinSurfaceNode_) {
938                 dstNodeSptr->leashWinSurfaceNode_->SetAnimationFinished();
939             }
940             WLOGFI("current window:%{public}u state: %{public}u", dstNodeSptr->GetWindowId(),
941                 static_cast<uint32_t>(dstNodeSptr->stateMachine_.GetCurrentState()));
942             FinishAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast<int32_t>(TraceTaskId::REMOTE_ANIMATION),
943                 "wms:async:ShowRemoteAnimation");
944             std::unordered_map<std::string, std::string> payload;
945             if (srcNodeWptr != nullptr) {
946                 payload["srcPid"] = std::to_string(srcNodeWptr->GetCallingPid());
947             }
948             ResSchedReport::GetInstance().ResSchedDataReport(
949                 Rosen::RES_TYPE_SHOW_REMOTE_ANIMATION, Rosen::REMOTE_ANIMATION_END, payload);
950         };
951     }
952     return CreateAnimationFinishedCallback(func, dstNode);
953 }
954 
ProcessAbility(const sptr<WindowNode> & srcNode,TransitionEvent event)955 static void ProcessAbility(const sptr<WindowNode>& srcNode, TransitionEvent event)
956 {
957     if (srcNode == nullptr) {
958         return;
959     }
960     switch (event) {
961         case TransitionEvent::CLOSE_BUTTON: {
962             WLOGFI("close windowId: %{public}u, name:%{public}s",
963                 srcNode->GetWindowId(), srcNode->GetWindowName().c_str());
964             WindowInnerManager::GetInstance().CloseAbility(srcNode);
965             break;
966         }
967         case TransitionEvent::MINIMIZE: {
968             WLOGFI("minimize windowId: %{public}u, name:%{public}s",
969                 srcNode->GetWindowId(), srcNode->GetWindowName().c_str());
970             WindowInnerManager::GetInstance().MinimizeAbility(srcNode, true);
971             break;
972         }
973         case TransitionEvent::CLOSE: // close by back
974         default:
975             break;
976     }
977 }
978 
NotifyAnimationUpdateWallpaper(sptr<WindowNode> node)979 void RemoteAnimation::NotifyAnimationUpdateWallpaper(sptr<WindowNode> node)
980 {
981     if (!CheckAnimationController()) {
982         return;
983     }
984     WLOGFI("NotifyAnimationUpdateWallpaper");
985     sptr<RSWindowAnimationTarget> srcTarget = CreateWindowAnimationTarget(nullptr, node);
986     // when wallpaper destroy, update with nullptr
987     windowAnimationController_->OnWallpaperUpdate(srcTarget);
988 }
989 
CreateHideAnimationFinishedCallback(const sptr<WindowNode> & srcNode,TransitionEvent event)990 sptr<RSWindowAnimationFinishedCallback> RemoteAnimation::CreateHideAnimationFinishedCallback(
991     const sptr<WindowNode>& srcNode, TransitionEvent event)
992 {
993     wptr<WindowNode> srcNodeWptr = srcNode;
994     // need add timeout check
995     std::function<void(void)> func;
996     if (!animationFirst_) {
997         func = [srcNodeWptr, event]() {
998             WLOGFI("RSWindowAnimation: not animationFirst use default callback!");
999             auto weakNode = srcNodeWptr.promote();
1000             if (weakNode == nullptr || weakNode->abilityToken_ == nullptr) {
1001                 WLOGFE("window node or ability token is nullptr");
1002                 return;
1003             }
1004             if (!weakNode->stateMachine_.IsWindowNodeHiddenOrHiding()) {
1005                 WLOGFE("window is not playing hide animation");
1006                 return;
1007             }
1008             ProcessAbility(weakNode, event);
1009             weakNode->stateMachine_.TransitionTo(WindowNodeState::HIDE_ANIMATION_DONE);
1010             FinishAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast<int32_t>(TraceTaskId::REMOTE_ANIMATION),
1011                 "wms:async:ShowRemoteAnimation");
1012         };
1013     } else {
1014         if (event != TransitionEvent::MINIMIZE) {
1015             GetAndDrawSnapShot(srcNode);
1016         }
1017         ProcessAbility(srcNode, event); // execute first when animationFirst
1018         func = [srcNodeWptr]() {
1019             WLOGFI("RSWindowAnimation: animationFirst use state machine process HideAnimationFinishedCallback!");
1020             auto srcNodeSptr = srcNodeWptr.promote();
1021             ProcessNodeStateTask(srcNodeSptr);
1022             FinishAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast<int32_t>(TraceTaskId::REMOTE_ANIMATION),
1023                 "wms:async:ShowRemoteAnimation");
1024         };
1025     }
1026     return CreateAnimationFinishedCallback(func, srcNode);
1027 }
1028 
ReportWindowAnimationCallbackTimeout(sptr<WindowNode> & node,const std::string & taskName)1029 static void ReportWindowAnimationCallbackTimeout(sptr<WindowNode>& node, const std::string& taskName)
1030 {
1031     std::ostringstream oss;
1032     oss << "animation callback time out: " << "window_name: " << node->GetWindowName()
1033         << "callbackName: " << taskName << ";";
1034     std::string info = oss.str();
1035     int32_t ret = HiSysEventWrite(
1036         OHOS::HiviewDFX::HiSysEvent::Domain::WINDOW_MANAGER,
1037         "ANIMATION_CALLBACK_TIMEOUT",
1038         OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
1039         "PID", node->GetCallingPid(),
1040         "UID", node->GetCallingUid(),
1041         "PACKAGE_NAME", node->abilityInfo_.abilityName_,
1042         "PROCESS_NAME", node->abilityInfo_.bundleName_,
1043         "MSG", info);
1044     if (ret != 0) {
1045         WLOGFE("Write HiSysEvent error, ret:%{public}d", ret);
1046     }
1047 }
1048 
CreateAnimationFinishedCallback(const std::function<void (void)> & callback,sptr<WindowNode> windowNode)1049 sptr<RSWindowAnimationFinishedCallback> RemoteAnimation::CreateAnimationFinishedCallback(
1050     const std::function<void(void)>& callback, sptr<WindowNode> windowNode)
1051 {
1052     if (callback == nullptr) {
1053         WLOGFE("callback is null!");
1054         return nullptr;
1055     }
1056     auto currentId = allocationId_.fetch_add(1);
1057     std::string timeOutTaskName = ANIMATION_TIME_OUT_TASK + std::to_string(currentId);
1058     wptr<WindowNode> weakNode = windowNode;
1059     auto timeoutFunc = [callback, timeOutTaskName, weakNode]() {
1060         WLOGFE("callback %{public}s is time out!", timeOutTaskName.c_str());
1061         callback();
1062         auto node = weakNode.promote();
1063         if (node == nullptr) {
1064             WLOGFW("window node is null or is home event, not report abnormal info!");
1065             return;
1066         }
1067         ReportWindowAnimationCallbackTimeout(node, timeOutTaskName);
1068     };
1069     auto callbackTask = [callback, timeOutTaskName]() {
1070         auto handler = wmsTaskHandler_.lock();
1071         if (handler != nullptr) {
1072             handler->RemoveTask("wms:" + timeOutTaskName);
1073             WLOGFD("remove task %{public}s since animationCallback Come", timeOutTaskName.c_str());
1074             handler->PostTask(callback, "wms:CreateAnimationFinishedCallback",
1075                 0, AppExecFwk::EventQueue::Priority::IMMEDIATE);
1076         }
1077     };
1078     auto handlerSptr = wmsTaskHandler_.lock();
1079     if (handlerSptr != nullptr) {
1080         handlerSptr->PostTask(timeoutFunc, "wms:" + timeOutTaskName, ANIMATION_TIME_OUT_MILLISECONDS);
1081         WLOGFD("PostTask task %{public}s", timeOutTaskName.c_str());
1082     }
1083     sptr<RSWindowAnimationFinishedCallback> finishCallback = new(std::nothrow) RSWindowAnimationFinishedCallback(
1084         callbackTask);
1085     if (finishCallback == nullptr) {
1086         WLOGFE("New RSIWindowAnimationFinishedCallback failed");
1087         callbackTask();
1088         return nullptr;
1089     }
1090     return finishCallback;
1091 }
1092 } // Rosen
1093 } // OHOS
1094