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 40namespace OHOS { 41namespace Rosen { 42namespace { 43constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "RemoteAnimation"}; 44const std::string ANIMATION_TIME_OUT_TASK = "remote_animation_time_out_task"; 45constexpr int64_t ANIMATION_TIME_OUT_MILLISECONDS = 3000; // 3000 is max time 46} 47bool RemoteAnimation::isRemoteAnimationEnable_ = true; 48std::atomic<uint32_t> RemoteAnimation::allocationId_ = 0; 49sptr<RSIWindowAnimationController> RemoteAnimation::windowAnimationController_ = nullptr; 50std::weak_ptr<AppExecFwk::EventHandler> RemoteAnimation::wmsTaskHandler_; 51wptr<WindowRoot> RemoteAnimation::windowRoot_; 52bool RemoteAnimation::animationFirst_ = false; 53wptr<WindowController> RemoteAnimation::windowController_ = nullptr; 54 55std::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 63void RemoteAnimation::SetAnimationFirst(bool animationFirst) 64{ 65 animationFirst_ = animationFirst; 66 WLOGFI("RSWindowAnimation:animationFirst: %{public}u!", static_cast<uint32_t>(animationFirst_)); 67} 68 69bool RemoteAnimation::IsRemoteAnimationEnabledAndFirst(DisplayId displayId) 70{ 71 return animationFirst_ && CheckRemoteAnimationEnabled(displayId); 72} 73 74WMError 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 103void RemoteAnimation::SetMainTaskHandler(std::shared_ptr<AppExecFwk::EventHandler> handler) 104{ 105 wmsTaskHandler_ = handler; 106} 107 108void RemoteAnimation::SetWindowControllerAndRoot(const sptr<WindowController>& windowController, 109 const sptr<WindowRoot>& windowRoot) 110{ 111 windowController_ = windowController; 112 windowRoot_ = windowRoot; 113} 114 115bool RemoteAnimation::CheckAnimationController() 116{ 117 if (windowAnimationController_ == nullptr) { 118 WLOGFD("RSWindowAnimation: windowAnimationController_ null!"); 119 return false; 120 } 121 return true; 122} 123 124bool 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 138bool 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->GetModeSupportInfo(), dstInfo)) { 159 WLOGFE("RSWindowAnimation: the mode of dstNode isn't supported, winId: %{public}u, mode: %{public}u, " 160 "modeSupportInfo: %{public}u", dstNode->GetWindowId(), dstNode->GetWindowMode(), 161 dstNode->GetModeSupportInfo()); 162 return false; 163 } 164 165 auto node = (dstNode != nullptr ? dstNode : srcNode); 166 return CheckRemoteAnimationEnabled(node->GetDisplayId()); 167} 168 169void 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 180static 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 213TransitionEvent 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 249sptr<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 287WMError 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 313void 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 343WMError 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 399WMError 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 425WMError 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 449void 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 488WMError 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 542void 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 571static 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 590WMError 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 630void 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 680WMError 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 695WMError 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 714sptr<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 768void 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 797void 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 825void 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 846static 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 866void 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 909sptr<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 952static 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 976void 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 987sptr<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 1026static 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 1046sptr<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