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