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