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