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         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 
GetTransitionEvent(sptr<WindowTransitionInfo> srcInfo,sptr<WindowTransitionInfo> dstInfo,const sptr<WindowNode> & srcNode,const sptr<WindowNode> & dstNode)213 TransitionEvent 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 
GetTransitionFinishedCallback(const sptr<WindowNode> & srcNode,const sptr<WindowNode> & dstNode)249 sptr<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 
NotifyAnimationStartApp(sptr<WindowTransitionInfo> srcInfo,const sptr<WindowNode> & srcNode,const sptr<WindowNode> & dstNode,sptr<RSWindowAnimationTarget> & dstTarget,sptr<RSWindowAnimationFinishedCallback> & finishedCallback)287 WMError 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 
GetExpectRect(const sptr<WindowNode> & dstNode,const sptr<RSWindowAnimationTarget> & dstTarget)313 void 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 
NotifyAnimationTransition(sptr<WindowTransitionInfo> srcInfo,sptr<WindowTransitionInfo> dstInfo,const sptr<WindowNode> & srcNode,const sptr<WindowNode> & dstNode)343 WMError 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 
NotifyAnimationMinimize(sptr<WindowTransitionInfo> srcInfo,const sptr<WindowNode> & srcNode)399 WMError 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 
NotifyAnimationClose(sptr<WindowTransitionInfo> srcInfo,const sptr<WindowNode> & srcNode,TransitionEvent event)425 WMError 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 
NotifyAnimationAbilityDied(sptr<WindowTransitionInfo> info)449 void 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 
NotifyAnimationBackTransition(sptr<WindowTransitionInfo> srcInfo,sptr<WindowTransitionInfo> dstInfo,const sptr<WindowNode> & srcNode,const sptr<WindowNode> & dstNode,const TransitionEvent event)488 WMError 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 
GetAnimationTargetsForHome(std::vector<sptr<RSWindowAnimationTarget>> & animationTargets,std::vector<wptr<WindowNode>> needMinimizeAppNodes)542 void 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 
GetAnimationHomeFinishCallback(std::function<void (void)> & func,std::vector<wptr<WindowNode>> needMinimizeAppNodes)571 static 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 
NotifyAnimationByHome()590 WMError 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 
NotifyAnimationTargetsUpdate(std::vector<uint32_t> & fullScreenWinIds,std::vector<uint32_t> & floatWinIds)630 void 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 
NotifyAnimationScreenUnlock(std::function<void (void)> callback,sptr<WindowNode> node)680 WMError 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 
GetWindowAnimationTargets(std::vector<uint32_t> missionIds,std::vector<sptr<RSWindowAnimationTarget>> & targets)695 WMError 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 
CreateWindowAnimationTarget(sptr<WindowTransitionInfo> info,const sptr<WindowNode> & windowNode)714 sptr<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 
PostProcessShowCallback(const sptr<WindowNode> & node)768 void 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 
ExecuteFinalStateTask(sptr<WindowNode> & node)797 void 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 
CallbackTimeOutProcess()825 void 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 
ReportWindowAnimationAbnormalInfo(sptr<WindowNode> & node)846 static 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 
ProcessNodeStateTask(sptr<WindowNode> & node)866 void 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 
CreateShowAnimationFinishedCallback(const sptr<WindowNode> & srcNode,const sptr<WindowNode> & dstNode,bool needMinimizeSrcNode)909 sptr<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 
ProcessAbility(const sptr<WindowNode> & srcNode,TransitionEvent event)952 static 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 
NotifyAnimationUpdateWallpaper(sptr<WindowNode> node)976 void 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 
CreateHideAnimationFinishedCallback(const sptr<WindowNode> & srcNode,TransitionEvent event)987 sptr<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 
ReportWindowAnimationCallbackTimeout(sptr<WindowNode> & node,const std::string & taskName)1026 static 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 
CreateAnimationFinishedCallback(const std::function<void (void)> & callback,sptr<WindowNode> windowNode)1046 sptr<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