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