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