目录

一.AppTransition过渡类型

二.AppTransition设置过渡类型调用栈信息

* 新活动中的窗口正在同一任务中的现有窗口之上打开。    int TRANSIT_ACTIVITY_OPEN = 6;

* 最顶层活动中的窗口正在关闭以显示同一任务中的前一个活动。    int TRANSIT_ACTIVITY_CLOSE = 7;

* 新任务中的窗口正在另一个活动任务中的现有窗口之上打开。    int TRANSIT_TASK_OPEN = 8;

* 最顶层活动中的一个窗口正在关闭,以显示不同任务中的前一个活动。    int TRANSIT_TASK_CLOSE = 9;

* 现有任务中的窗口显示在另一个活动任务中现有任务的顶部。    int TRANSIT_TASK_TO_FRONT = 10;

* 现有任务中的窗口被放置在所有其他任务下方。    int TRANSIT_TASK_TO_BACK = 11;

* Keyguard 即将消失。    int TRANSIT_KEYGUARD_GOING_AWAY = 20;

三.AppTransition 执行前的调用栈信息

(1)非冷启动应用

(2)锁屏消失时

(3)最近任务显示已有堆栈的Actiivty

(4)冷启动应用

四.AppTransition的过渡动画的启动

(1)AppTransitionController.handleAppTransitionReady 准备过渡动画

(2)AppTransitionController.applyAnimations 设置过渡动画

(3)WindowContainer.applyAnimation 启动动画

(4)WindowContainer.getAnimationAdapter 获取远程/窗口/应用过渡动画

(5)AppTransition.loadAnimation 获取动画实例

五.总结


一.AppTransition过渡类型

    * 未设置过渡。int TRANSIT_UNSET = -1;* 没有过渡动画。int TRANSIT_NONE = 0;* 新活动中的窗口正在同一任务中的现有窗口之上打开。int TRANSIT_ACTIVITY_OPEN = 6;* 最顶层活动中的窗口正在关闭以显示同一任务中的前一个活动。int TRANSIT_ACTIVITY_CLOSE = 7;* 新任务中的窗口正在另一个活动任务中的现有窗口之上打开。int TRANSIT_TASK_OPEN = 8;* 最顶层活动中的一个窗口正在关闭,以显示不同任务中的前一个活动。int TRANSIT_TASK_CLOSE = 9;* 现有任务中的窗口显示在另一个活动任务中现有任务的顶部。int TRANSIT_TASK_TO_FRONT = 10;* 现有任务中的窗口被放置在所有其他任务下方。int TRANSIT_TASK_TO_BACK = 11;* 新活动中没有墙纸的窗口会在有墙纸的窗口之上打开,从而有效地关闭墙纸。int TRANSIT_WALLPAPER_CLOSE = 12;* 新活动中带有墙纸的窗口会在没有墙纸的窗口上打开,从而有效地打开墙纸。int TRANSIT_WALLPAPER_OPEN = 13;* 新活动中的一个窗口在现有活动的顶部打开,并且两者都在墙纸的顶部。int TRANSIT_WALLPAPER_INTRA_OPEN = 14;* 最顶部活动中的窗口正在关闭以显示之前的活动,并且两者都位于墙纸的顶部。int TRANSIT_WALLPAPER_INTRA_CLOSE = 15;* 新任务中的一个窗口在另一个活动的任务中的现有窗口后面打开。新窗口将短暂显示,然后消失。int TRANSIT_TASK_OPEN_BEHIND = 16;* 正在重新启动活动(例如,由于配置更改)。int TRANSIT_ACTIVITY_RELAUNCH = 18;* 正在对接最近的任务。int TRANSIT_DOCK_TASK_FROM_RECENTS = 19;* Keyguard 即将消失。int TRANSIT_KEYGUARD_GOING_AWAY = 20;* Keyguard 将消失,显示背后请求墙纸的活动。int TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER = 21;* Keyguard 被遮挡。int TRANSIT_KEYGUARD_OCCLUDE = 22;* Keyguard 未被遮挡。int TRANSIT_KEYGUARD_UNOCCLUDE = 23;* 正在打开一个半透明的活动。int TRANSIT_TRANSLUCENT_ACTIVITY_OPEN = 24;* 一个半透明的活动正在关闭。int TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE = 25;* 正在关闭崩溃的活动。int TRANSIT_CRASHING_ACTIVITY_CLOSE = 26;* 一项任务正在改变窗口模式int TRANSIT_TASK_CHANGE_WINDOWING_MODE = 27;* 由于第一个活动已启动或正在打开,因此正在显示只能包含一个任务的显示。int TRANSIT_SHOW_SINGLE_TASK_DISPLAY = 28; 

二.AppTransition设置过渡类型调用栈信息

* 新活动中的窗口正在同一任务中的现有窗口之上打开。
    int TRANSIT_ACTIVITY_OPEN = 6;

(1)锁屏消失出现Activity时
        com.android.server.wm.DisplayContent.prepareAppTransition
        com.android.server.wm.DisplayContent.prepareAppTransition
        com.android.server.wm.ActivityStack.resumeTopActivityInnerLocked
        com.android.server.wm.ActivityStack.resumeTopActivityUncheckedLocked
        com.android.server.wm.ActivityRecord.makeActiveIfNeeded
        com.android.server.wm.RootWindowContainer.resumeFocusedStacksTopActivities
        com.android.server.wm.RootWindowContainer.resumeFocusedStacksTopActivities
        com.android.server.wm.RootWindowContainer.applySleepTokens
        com.android.server.wm.ActivityTaskManagerService.updateSleepIfNeededLocked
        com.android.server.wm.RootWindowContainer.removeSleepToken
        com.android.server.wm.RootWindowContainer.access$200
        com.android.server.wm.RootWindowContainer$SleepTokenImpl.release
        com.android.server.wm.KeyguardController$KeyguardDisplayState.releaseSleepToken
        com.android.server.wm.KeyguardController.updateKeyguardSleepToken
        com.android.server.wm.KeyguardController.updateKeyguardSleepToken
        com.android.server.wm.KeyguardController.keyguardGoingAway
        com.android.server.wm.ActivityTaskManagerService.keyguardGoingAway
        android.app.IActivityTaskManager$Stub.onTransact
    (2)应用中进入新的Activity时
        com.android.server.wm.DisplayContent.prepareAppTransition
        com.android.server.wm.DisplayContent.prepareAppTransition
        com.android.server.wm.ActivityStack.startActivityLocked
        com.android.server.wm.ActivityStarter.startActivityInner
        com.android.server.wm.ActivityStarter.startActivityUnchecked
        com.android.server.wm.ActivityStarter.executeRequest
        com.android.server.wm.ActivityStarter.execute
        com.android.server.wm.ActivityTaskManagerService.startActivityAsUser
        com.android.server.wm.ActivityTaskManagerService.startActivityAsUser
        com.android.server.wm.ActivityTaskManagerService.startActivity
        android.app.IActivityTaskManager$Stub.onTransact
    (3)应用中新的Activity OnResume时
        com.android.server.wm.DisplayContent.prepareAppTransition
        com.android.server.wm.DisplayContent.prepareAppTransition
        com.android.server.wm.ActivityStack.resumeTopActivityInnerLocked
        com.android.server.wm.ActivityStack.resumeTopActivityUncheckedLocked
        com.android.server.wm.RootWindowContainer.resumeFocusedStacksTopActivities
        com.android.server.wm.ActivityStack.completePauseLocked
        com.android.server.wm.ActivityRecord.activityPaused
        com.android.server.wm.ActivityTaskManagerService.activityPaused
        android.app.IActivityTaskManager$Stub.onTransact
    (4)前台应用被杀死时,需要显示的Activity OnResume时
        com.android.server.wm.DisplayContent.prepareAppTransition
        com.android.server.wm.DisplayContent.prepareAppTransition
        com.android.server.wm.ActivityStack.resumeTopActivityInnerLocked
        com.android.server.wm.ActivityStack.resumeTopActivityUncheckedLocked
        com.android.server.wm.ActivityRecord.makeActiveIfNeeded
        com.android.server.wm.RootWindowContainer.resumeFocusedStacksTopActivities
        com.android.server.wm.RootWindowContainer.resumeFocusedStacksTopActivities
        com.android.server.wm.ActivityTaskManagerService$LocalService.handleAppDied
        com.android.server.am.ActivityManagerService.handleAppDiedLocked
        com.android.server.am.ActivityManagerService.appDiedLocked
        com.android.server.am.ActivityManagerService$AppDeathRecipient.binderDied

* 最顶层活动中的窗口正在关闭以显示同一任务中的前一个活动。
    int TRANSIT_ACTIVITY_CLOSE = 7;

(1)应用中按back键推出Activity时
        com.android.server.wm.DisplayContent.prepareAppTransition
        com.android.server.wm.DisplayContent.prepareAppTransition
        com.android.server.wm.ActivityRecord.finishIfPossible
        com.android.server.wm.ActivityTaskManagerService.finishActivity
        android.app.IActivityTaskManager$Stub.onTransact
    (2)应用中按back键需要显示的Activity OnResume时
        com.android.server.wm.DisplayContent.prepareAppTransition
        com.android.server.wm.DisplayContent.prepareAppTransition
        com.android.server.wm.ActivityStack.resumeTopActivityInnerLocked
        com.android.server.wm.ActivityStack.resumeTopActivityUncheckedLocked
        com.android.server.wm.RootWindowContainer.resumeFocusedStacksTopActivities
        com.android.server.wm.ActivityStack.completePauseLocked
        com.android.server.wm.ActivityRecord.activityPaused
        com.android.server.wm.ActivityTaskManagerService.activityPaused
        android.app.IActivityTaskManager$Stub.onTransact

* 新任务中的窗口正在另一个活动任务中的现有窗口之上打开。
    int TRANSIT_TASK_OPEN = 8;

(1)进入新的堆栈,新的Activity启动时
        com.android.server.wm.DisplayContent.prepareAppTransition
        com.android.server.wm.DisplayContent.prepareAppTransition
        com.android.server.wm.ActivityStack.startActivityLocked
        com.android.server.wm.ActivityStarter.startActivityInner
        com.android.server.wm.ActivityStarter.startActivityUnchecked
        com.android.server.wm.ActivityStarter.executeRequest
        com.android.server.wm.ActivityStarter.execute
        com.android.server.wm.ActivityTaskManagerService.startActivityAsUser
        com.android.server.wm.ActivityTaskManagerService.startActivityAsUser
        com.android.server.wm.ActivityTaskManagerService.startActivity
        android.app.IActivityTaskManager$Stub.onTransact
    (2)进入新的堆栈,新的Activity OnResume时
        com.android.server.wm.DisplayContent.prepareAppTransition
        com.android.server.wm.DisplayContent.prepareAppTransition
        com.android.server.wm.ActivityStack.resumeTopActivityInnerLocked
        com.android.server.wm.ActivityStack.resumeTopActivityUncheckedLocked
        com.android.server.wm.RootWindowContainer.resumeFocusedStacksTopActivities
        com.android.server.wm.ActivityStack.completePauseLocked
        com.android.server.wm.ActivityRecord.activityPaused
        com.android.server.wm.ActivityTaskManagerService.activityPaused
        android.app.IActivityTaskManager$Stub.onTransact

* 最顶层活动中的一个窗口正在关闭,以显示不同任务中的前一个活动。
    int TRANSIT_TASK_CLOSE = 9;

(1)应用中按back键推出Activity堆栈时
        com.android.server.wm.DisplayContent.prepareAppTransition
        com.android.server.wm.DisplayContent.prepareAppTransition
        com.android.server.wm.ActivityRecord.finishIfPossible
        com.android.server.wm.ActivityTaskManagerService.finishActivity
        android.app.IActivityTaskManager$Stub.onTransact
    (2)应用中按back键新的堆栈Activity OnResume时
        com.android.server.wm.DisplayContent.prepareAppTransition
        com.android.server.wm.DisplayContent.prepareAppTransition
        com.android.server.wm.ActivityStack.resumeTopActivityInnerLocked
        com.android.server.wm.ActivityStack.resumeTopActivityUncheckedLocked
        com.android.server.wm.RootWindowContainer.resumeFocusedStacksTopActivities
        com.android.server.wm.ActivityStack.completePauseLocked
        com.android.server.wm.ActivityRecord.activityPaused
        com.android.server.wm.ActivityTaskManagerService.activityPaused
        android.app.IActivityTaskManager$Stub.onTransact

* 现有任务中的窗口显示在另一个活动任务中现有任务的顶部。
    int TRANSIT_TASK_TO_FRONT = 10;

(1)最近任务进入已有的堆栈
        com.android.server.wm.DisplayContent.prepareAppTransition
        com.android.server.wm.ActivityStack.updateTransitLocked
        com.android.server.wm.ActivityStack.moveTaskToFront
        com.android.server.wm.ActivityStack.moveTaskToFront
        com.android.server.wm.ActivityStackSupervisor.findTaskToMoveToFront
        com.android.server.wm.ActivityTaskManagerService.moveTaskToFrontLocked
        com.android.server.wm.ActivityStackSupervisor.startActivityFromRecents
        com.android.server.wm.ActivityTaskManagerService.startActivityFromRecents
        android.app.IActivityTaskManager$Stub.onTransact
    (2)桌面点击进入已有的堆栈
        com.android.server.wm.DisplayContent.prepareAppTransition
        com.android.server.wm.ActivityStack.updateTransitLocked
        com.android.server.wm.ActivityStack.moveTaskToFront
        com.android.server.wm.ActivityStarter.setTargetStackIfNeeded
        com.android.server.wm.ActivityStarter.recycleTask
        com.android.server.wm.ActivityStarter.startActivityInner
        com.android.server.wm.ActivityStarter.startActivityUnchecked
        com.android.server.wm.ActivityStarter.executeRequest
        com.android.server.wm.ActivityStarter.execute
        com.android.server.wm.ActivityTaskManagerService.startActivityAsUser
        com.android.server.wm.ActivityTaskManagerService.startActivityAsUser
        com.android.server.wm.ActivityTaskManagerService.startActivity
        android.app.IActivityTaskManager$Stub.onTransact
    (3)应用中点击Home键时
        com.android.server.wm.DisplayContent.prepareAppTransition
        com.android.server.wm.ActivityStack.updateTransitLocked
        com.android.server.wm.ActivityStack.moveTaskToFront
        com.android.server.wm.ActivityStarter.setTargetStackIfNeeded
        com.android.server.wm.ActivityStarter.recycleTask
        com.android.server.wm.ActivityStarter.startActivityInner
        com.android.server.wm.ActivityStarter.startActivityUnchecked
        com.android.server.wm.ActivityStarter.executeRequest
        com.android.server.wm.ActivityStarter.execute
        com.android.server.wm.ActivityStartController.startHomeActivity
        com.android.server.wm.RootWindowContainer.startHomeOnTaskDisplayArea
        com.android.server.wm.RootWindowContainer.startHomeOnDisplay
        com.android.server.wm.ActivityTaskManagerService$LocalService.startHomeOnDisplay
        com.android.server.policy.PhoneWindowManager.startDockOrHome
        com.android.server.policy.PhoneWindowManager.launchHomeFromHotKey
        com.android.server.policy.PhoneWindowManager.launchHomeFromHotKey
        com.android.server.policy.PhoneWindowManager.handleShortPressOnHome
        com.android.server.policy.PhoneWindowManager.access$2700
        com.android.server.policy.PhoneWindowManager$DisplayHomeButtonHandler.lambda$handleHomeButton$0$PhoneWindowManager$DisplayHomeButtonHandler

* 现有任务中的窗口被放置在所有其他任务下方。
    int TRANSIT_TASK_TO_BACK = 11;

(1)应用主动调用Activity.moveTaskToBack()时出现(这个方法不会改变task中的activity中的顺序,效果基本等同于home键)
        com.android.server.wm.DisplayContent.prepareAppTransition
        com.android.server.wm.DisplayContent.prepareAppTransition
        com.android.server.wm.ActivityStack.moveTaskToBack
        com.android.server.wm.ActivityTaskManagerService.moveActivityTaskToBack
        android.app.IActivityTaskManager$Stub.onTransact

* Keyguard 即将消失。
    int TRANSIT_KEYGUARD_GOING_AWAY = 20;

com.android.server.wm.DisplayContent.prepareAppTransition
        com.android.server.wm.KeyguardController.keyguardGoingAway
        com.android.server.wm.ActivityTaskManagerService.keyguardGoingAway
        android.app.IActivityTaskManager$Stub.onTransact

注意:有时会一次Activity切换时会出现多个过渡类型的设置,例如startActivity时会设置一个,Activity OnResume时会出现一次,所以真正的过渡类型,还需要AppTransition.prepareAppTransitionLocked筛选。

    /*** @return true if transition is not running and should not be skipped, false if transition is*         already running*/boolean prepareAppTransitionLocked(@TransitionType int transit, boolean alwaysKeepCurrent,@TransitionFlags int flags, boolean forceOverride) {ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,"Prepare app transition: transit=%s %s alwaysKeepCurrent=%b displayId=%d "+ "Callers=%s",appTransitionToString(transit), this, alwaysKeepCurrent,mDisplayContent.getDisplayId(), Debug.getCallers(20));final boolean allowSetCrashing = !isKeyguardTransit(mNextAppTransition)&& transit == TRANSIT_CRASHING_ACTIVITY_CLOSE;if (forceOverride || isKeyguardTransit(transit) || !isTransitionSet()|| mNextAppTransition == TRANSIT_NONE || allowSetCrashing) {setAppTransition(transit, flags);}// We never want to change from a Keyguard transit to a non-Keyguard transit, as our logic// relies on the fact that we always execute a Keyguard transition after preparing one. We// also don't want to change away from a crashing transition.else if (!alwaysKeepCurrent && !isKeyguardTransit(mNextAppTransition)&& mNextAppTransition != TRANSIT_CRASHING_ACTIVITY_CLOSE) {if (transit == TRANSIT_TASK_OPEN && isTransitionEqual(TRANSIT_TASK_CLOSE)) {// Opening a new task always supersedes a close for the anim.setAppTransition(transit, flags);} else if (transit == TRANSIT_ACTIVITY_OPEN&& isTransitionEqual(TRANSIT_ACTIVITY_CLOSE)) {// Opening a new activity always supersedes a close for the anim.setAppTransition(transit, flags);} else if (isTaskTransit(transit) && isActivityTransit(mNextAppTransition)) {// Task animations always supersede activity animations, because if we have both, it// usually means that activity transition were just trampoline activities.setAppTransition(transit, flags);}}boolean prepared = prepare();if (isTransitionSet()) {removeAppTransitionTimeoutCallbacks();mHandler.postDelayed(mHandleAppTransitionTimeoutRunnable, APP_TRANSITION_TIMEOUT_MS);}return prepared;}

三.AppTransition 执行前的调用栈信息

DisplayContent中是应用过渡转化的过程:

    void executeAppTransition() {if (mAppTransition.isTransitionSet()) {ProtoLog.w(WM_DEBUG_APP_TRANSITIONS,"Execute app transition: %s, displayId: %d Callers=%s",mAppTransition, mDisplayId, Debug.getCallers(20));mAppTransition.setReady();mWmService.mWindowPlacerLocked.requestTraversal();}}

此过程会设置AppTransition的状态为准备状态,同时调用WindowSurfacePlacer.requestTraversal对WMS状态做刷新。

(1)非冷启动应用

com.android.server.wm.RootWindowContainer.executeAppTransitionForAllDisplay
com.android.server.wm.ActivityStackSupervisor.reportResumedActivityLocked
com.android.server.wm.ActivityRecord.completeResumeLocked
com.android.server.wm.ActivityStack.resumeTopActivityInnerLocked
com.android.server.wm.ActivityStack.resumeTopActivityUncheckedLocked
com.android.server.wm.RootWindowContainer.resumeFocusedStacksTopActivities
com.android.server.wm.ActivityStack.completePauseLocked
com.android.server.wm.ActivityRecord.activityPaused
com.android.server.wm.ActivityTaskManagerService.activityPaused
android.app.IActivityTaskManager$Stub.onTransact

(2)锁屏消失时

com.android.server.wm.WindowManagerService.executeAppTransition
com.android.server.wm.KeyguardController.keyguardGoingAway
com.android.server.wm.ActivityTaskManagerService.keyguardGoingAway
android.app.IActivityTaskManager$Stub.onTransact

(3)最近任务显示已有堆栈的Actiivty

com.android.server.wm.RootWindowContainer.executeAppTransitionForAllDisplay
com.android.server.wm.ActivityStackSupervisor.reportResumedActivityLocked
com.android.server.wm.ActivityRecord.completeResumeLocked
com.android.server.wm.ActivityStack.resumeTopActivityInnerLocked
com.android.server.wm.ActivityStack.resumeTopActivityUncheckedLocked
com.android.server.wm.RootWindowContainer.resumeFocusedStacksTopActivities
com.android.server.wm.ActivityStarter.resumeTargetStackIfNeeded
com.android.server.wm.ActivityStarter.recycleTask
com.android.server.wm.ActivityStarter.startActivityInner
com.android.server.wm.ActivityStarter.startActivityUnchecked
com.android.server.wm.ActivityStarter.executeRequest
com.android.server.wm.ActivityStarter.execute
com.android.server.wm.ActivityTaskManagerService.startActivityAsUser
com.android.server.wm.ActivityTaskManagerService.startActivityAsUser
com.android.server.wm.ActivityTaskManagerService.startActivity
android.app.IActivityTaskManager$Stub.onTransact

(4)冷启动应用

com.android.server.wm.RootWindowContainer.executeAppTransitionForAllDisplay
com.android.server.wm.ActivityStackSupervisor.reportResumedActivityLocked
com.android.server.wm.ActivityRecord.completeResumeLocked
com.android.server.wm.ActivityStack.minimalResumeActivityLocked
com.android.server.wm.ActivityStackSupervisor.realStartActivityLocked
com.android.server.wm.RootWindowContainer.startActivityForAttachedApplicationIfNeeded
com.android.server.wm.RootWindowContainer.lambda$5fbF65VSmaJkPHxEhceOGTat7JE
com.android.server.wm.-$$Lambda$RootWindowContainer$5fbF65VSmaJkPHxEhceOGTat7JE.apply
com.android.internal.util.function.pooled.PooledLambdaImpl.doInvoke
com.android.internal.util.function.pooled.PooledLambdaImpl.invoke
com.android.internal.util.function.pooled.OmniFunction.apply
com.android.server.wm.ActivityRecord.forAllActivities
com.android.server.wm.WindowContainer.forAllActivities
com.android.server.wm.WindowContainer.forAllActivities
com.android.server.wm.RootWindowContainer.attachApplication
com.android.server.wm.ActivityTaskManagerService$LocalService.attachApplication
com.android.server.am.ActivityManagerService.attachApplicationLocked
com.android.server.am.ActivityManagerService.attachApplication
android.app.IActivityManager$Stub.onTransact
com.android.server.am.ActivityManagerService.onTransact

四.AppTransition的过渡动画的启动

com.android.server.wm.RootWindowContainer.checkAppTransitionReady
com.android.server.wm.RootWindowContainer.performSurfacePlacement
com.android.server.wm.WindowSurfacePlacer.performSurfacePlacementLoop
com.android.server.wm.WindowSurfacePlacer.performSurfacePlacement

    private void checkAppTransitionReady(WindowSurfacePlacer surfacePlacer) {// Trace all displays app transition by Z-order for pending layout change.for (int i = mChildren.size() - 1; i >= 0; --i) {final DisplayContent curDisplay = mChildren.get(i);// If we are ready to perform an app transition, check through all of the app tokens// to be shown and see if they are ready to go.if (curDisplay.mAppTransition.isReady()) {// handleAppTransitionReady may modify curDisplay.pendingLayoutChanges.curDisplay.mAppTransitionController.handleAppTransitionReady();if (DEBUG_LAYOUT_REPEATS) {surfacePlacer.debugLayoutRepeats("after handleAppTransitionReady",curDisplay.pendingLayoutChanges);}}if (curDisplay.mAppTransition.isRunning() && !curDisplay.isAppTransitioning()) {// We have finished the animation of an app transition. To do this, we have// delayed a lot of operations like showing and hiding apps, moving apps in// Z-order, etc.// The app token list reflects the correct Z-order, but the window list may now// be out of sync with it. So here we will just rebuild the entire app window// list. Fun!curDisplay.handleAnimatingStoppedAndTransition();if (DEBUG_LAYOUT_REPEATS) {surfacePlacer.debugLayoutRepeats("after handleAnimStopAndXitionLock",curDisplay.pendingLayoutChanges);}}}}

如上源码,checkAppTransitionReady会判断DisplayContent的AppTransition是否处于准备状态,处于准备状态的时候就调用AppTransitionController.handleAppTransitionReady。

(1)AppTransitionController.handleAppTransitionReady 准备过渡动画

    /*** Handle application transition for given display.*/void handleAppTransitionReady() {mTempTransitionReasons.clear();/*  对即将打开或者改变的组件做判断是否需要开始过渡主要有:屏幕旋转时推迟,组件未准备好时推迟,远程动画时推迟,壁纸未准备好时推迟 */if (!transitionGoodToGo(mDisplayContent.mOpeningApps, mTempTransitionReasons)|| !transitionGoodToGo(mDisplayContent.mChangingContainers,mTempTransitionReasons)) {return;}Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "AppTransitionReady");ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "**** GOOD TO GO");/*判断是否需要跳过过渡*/final AppTransition appTransition = mDisplayContent.mAppTransition;int transit = appTransition.getAppTransition();if (mDisplayContent.mSkipAppTransitionAnimation && !isKeyguardGoingAwayTransit(transit)) {transit = WindowManager.TRANSIT_UNSET;}/*清理环境属性*/mDisplayContent.mSkipAppTransitionAnimation = false;mDisplayContent.mNoAnimationNotifyOnTransitionFinished.clear();appTransition.removeAppTransitionTimeoutCallbacks();mDisplayContent.mWallpaperMayChange = false;/*清理发生变化的组件的动画属性*/int appCount = mDisplayContent.mOpeningApps.size();for (int i = 0; i < appCount; ++i) {// Clearing the mAnimatingExit flag before entering animation. It's set to true if app// window is removed, or window relayout to invisible. This also affects window// visibility. We need to clear it *before* maybeUpdateTransitToWallpaper() as the// transition selection depends on wallpaper target visibility.mDisplayContent.mOpeningApps.valueAtUnchecked(i).clearAnimatingFlags();}appCount = mDisplayContent.mChangingContainers.size();for (int i = 0; i < appCount; ++i) {// Clearing for same reason as above.final ActivityRecord activity = getAppFromContainer(mDisplayContent.mChangingContainers.valueAtUnchecked(i));if (activity != null) {activity.clearAnimatingFlags();}}/*通过变化的组件对壁纸调整*/// Adjust wallpaper before we pull the lower/upper target, since pending changes// (like the clearAnimatingFlags() above) might affect wallpaper target result.// Or, the opening app window should be a wallpaper target.mWallpaperControllerLocked.adjustWallpaperWindowsForAppTransitionIfNeeded(mDisplayContent.mOpeningApps);/*变化的组件为壁纸目标时*/// Determine if closing and opening app token sets are wallpaper targets, in which case// special animations are needed.final boolean hasWallpaperTarget = mWallpaperControllerLocked.getWallpaperTarget() != null;final boolean openingAppHasWallpaper = canBeWallpaperTarget(mDisplayContent.mOpeningApps)&& hasWallpaperTarget;final boolean closingAppHasWallpaper = canBeWallpaperTarget(mDisplayContent.mClosingApps)&& hasWallpaperTarget;/*变化的组件为透明时做特殊处理TRANSIT_TRANSLUCENT_ACTIVITY_CLOSETRANSIT_TRANSLUCENT_ACTIVITY_OPEN*/transit = maybeUpdateTransitToTranslucentAnim(transit);/*变化的组件为壁纸目标时做特殊处理,改变过渡方式TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPERTRANSIT_WALLPAPER_INTRA_OPENTRANSIT_WALLPAPER_INTRA_CLOSETRANSIT_WALLPAPER_CLOSETRANSIT_WALLPAPER_OPEN*/transit = maybeUpdateTransitToWallpaper(transit, openingAppHasWallpaper,closingAppHasWallpaper);// Find the layout params of the top-most application window in the tokens, which is// what will control the animation theme. If all closing windows are obscured, then there is// no need to do an animation. This is the case, for example, when this transition is being// done behind a dream window./*获取各个变化的组件的TOP,适配远程动画*/final ArraySet<Integer> activityTypes = collectActivityTypes(mDisplayContent.mOpeningApps,mDisplayContent.mClosingApps, mDisplayContent.mChangingContainers);final ActivityRecord animLpActivity = findAnimLayoutParamsToken(transit, activityTypes);final ActivityRecord topOpeningApp =getTopApp(mDisplayContent.mOpeningApps, false /* ignoreHidden */);final ActivityRecord topClosingApp =getTopApp(mDisplayContent.mClosingApps, false /* ignoreHidden */);final ActivityRecord topChangingApp =getTopApp(mDisplayContent.mChangingContainers, false /* ignoreHidden */);final WindowManager.LayoutParams animLp = getAnimLp(animLpActivity);overrideWithRemoteAnimationIfSet(animLpActivity, transit, activityTypes);/*获取变化组件是否为语音交互咦! ||前后两个函数参数都相同*/final boolean voiceInteraction = containsVoiceInteraction(mDisplayContent.mOpeningApps)|| containsVoiceInteraction(mDisplayContent.mOpeningApps);/*暂停系统界面动画,开始设置过渡动画*/final int layoutRedo;mService.mSurfaceAnimationRunner.deferStartingAnimations();try {/*对待关闭/待打开的组件启动过渡动画,此函数较复杂,下面会有详细说明:*/applyAnimations(mDisplayContent.mOpeningApps, mDisplayContent.mClosingApps, transit,animLp, voiceInteraction);/*处理待关闭的组件,设置其属性使,其满足运行过渡动画的条件:*/handleClosingApps();/*处理待打开的组件,设置其属性使,其满足运行过渡动画的条件:*/handleOpeningApps();/*对待改变的窗口启动过渡动画,流程上和上面applyAnimations会有重合*/handleChangingApps(transit);/*设置AppTransition最新属性*/appTransition.setLastAppTransition(transit, topOpeningApp,topClosingApp, topChangingApp);/*AppTransition通知监听者是否需要重新布局*/final int flags = appTransition.getTransitFlags();layoutRedo = appTransition.goodToGo(transit, topOpeningApp,mDisplayContent.mOpeningApps);/*针对非应用基础组件的窗口的过渡动画,如壁纸,状态栏,虚拟按键,悬浮窗等*/handleNonAppWindowsInTransition(transit, flags);/*清理环境属性*/appTransition.postAnimationCallback();appTransition.clear();} finally {/*恢复系统界面动画*/mService.mSurfaceAnimationRunner.continueStartingAnimations();}/*系统缩略图界面动画*/mService.mTaskSnapshotController.onTransitionStarting(mDisplayContent);/*清理环境属性*/mDisplayContent.mOpeningApps.clear();mDisplayContent.mClosingApps.clear();mDisplayContent.mChangingContainers.clear();mDisplayContent.mUnknownAppVisibilityController.clear();// This has changed the visibility of windows, so perform// a new layout to get them all up-to-date.mDisplayContent.setLayoutNeeded();/*重新计算输入法目标窗口*/mDisplayContent.computeImeTarget(true /* updateImeTarget */);mService.mAtmService.mStackSupervisor.getActivityMetricsLogger().notifyTransitionStarting(mTempTransitionReasons);if (transit == TRANSIT_SHOW_SINGLE_TASK_DISPLAY) {mService.mAnimator.addAfterPrepareSurfacesRunnable(() -> {mService.mAtmInternal.notifySingleTaskDisplayDrawn(mDisplayContent.getDisplayId());});}Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);mDisplayContent.pendingLayoutChanges |=layoutRedo | FINISH_LAYOUT_REDO_LAYOUT | FINISH_LAYOUT_REDO_CONFIG;}

(2)AppTransitionController.applyAnimations 设置过渡动画

    /** @param openingApps 应用过渡动画的打开应用列表。* @param closedApps 应用程序过渡动画所应用的关闭应用程序列表。* @param trans 当前过渡类型。* @param animLp 应用程序过渡动画在其中运行的布局参数。* @param voiceInteraction {@code true} 如果此转换中的应用程序之一属于语音交互会话驱动任务。 被handleAppTransitionReady调用*/private void applyAnimations(ArraySet<ActivityRecord> openingApps,ArraySet<ActivityRecord> closingApps, @TransitionType int transit,LayoutParams animLp, boolean voiceInteraction) {/*跳过应用动画*/if (transit == WindowManager.TRANSIT_UNSET|| (openingApps.isEmpty() && closingApps.isEmpty())) {return;}/*获取openingApps过渡动画的目标,会根据其openingApps和closingApps的关系,向上找寻父类,直到同一父类时停止同一应用时为ActivityRecord不同应用时为Task解锁时无closingApps则为DefaultTaskDisplayArea*/final ArraySet<WindowContainer> openingWcs = getAnimationTargets(openingApps, closingApps, true /* visible */);/*获取closingApps过渡动画的目标,会根据其openingApps和closingApps的关系,向上找寻父类,直到同一父类时停止同一应用时为ActivityRecord不同应用时为Task解锁时无closingApps则为DefaultTaskDisplayArea*/final ArraySet<WindowContainer> closingWcs = getAnimationTargets(openingApps, closingApps, false /* visible */);/*将过渡动画应用于openingWcs*/applyAnimations(openingWcs, openingApps, transit, true /* visible */, animLp,voiceInteraction);/*将过渡动画应用于closingWcs*/applyAnimations(closingWcs, closingApps, transit, false /* visible */, animLp,voiceInteraction);final AccessibilityController accessibilityController =mDisplayContent.mWmService.mAccessibilityController;if (accessibilityController != null) {accessibilityController.onAppWindowTransitionLocked(mDisplayContent.getDisplayId(), transit);}}/*将过渡动画应用于目标容器*/private void applyAnimations(ArraySet<WindowContainer> wcs, ArraySet<ActivityRecord> apps,@TransitionType int transit, boolean visible, LayoutParams animLp,boolean voiceInteraction) {final int wcsCount = wcs.size();for (int i = 0; i < wcsCount; i++) {final WindowContainer wc = wcs.valueAt(i);// If app transition animation target is promoted to higher level, SurfaceAnimator// triggers WC#onAnimationFinished only on the promoted target. So we need to take care// of triggering AR#onAnimationFinished on each ActivityRecord which is a part of the// app transition./*目标组件可能会被抬升至较高级的组件(如:DefaultTaskDisplayArea),onAnimationFinished只会传递到最高的组件无法向下传播,故添加目标至高级的组件中使其能够调用到onAnimationFinished*/final ArrayList<ActivityRecord> transitioningDescendants = new ArrayList<>();for (int j = 0; j < apps.size(); ++j) {final ActivityRecord app = apps.valueAt(j);if (app.isDescendantOf(wc)) {transitioningDescendants.add(app);}}/*目标组件应用过渡动画(applyAnimation函数不仅在WindowContainer实现,也在ActivityRecord中实现了,ActivityRecord是涉及到StartingWindow,此处就不分析了)*/wc.applyAnimation(animLp, transit, visible, voiceInteraction, transitioningDescendants);}}

(3)WindowContainer.applyAnimation 启动动画

    /** 根据窗口层次结构中给定的布局属性应用过渡动画。** @param lp 窗口的布局参数。* @param trans 应用程序转换类型指示要应用的转换类型。* @param enter 应用过渡是否进入过渡(visible)。* @param isVoiceInteraction 容器是否参与语音交互。* @param sources {@link ActivityRecord}s which causes this app transition animation.** @return {@code true} 当容器应用应用转换时,{@code false} 如果应用转换被禁用或跳过。被AppTransitionController.applyAnimations调用*/boolean applyAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,boolean isVoiceInteraction, @Nullable ArrayList<WindowContainer> sources) {/*系统级的关闭过渡动画*/if (mWmService.mDisableTransitionAnimation) {ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,"applyAnimation: transition animation is disabled or skipped. "+ "container=%s", this);cancelAnimation();return false;}// Only apply an animation if the display isn't frozen. If it is frozen, there is no reason// to animate and it can cause strange artifacts when we unfreeze the display if some// different animation is running./*屏幕固定时不允许过渡动画*/try {Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "WC#applyAnimation");if (okToAnimate()) {applyAnimationUnchecked(lp, enter, transit, isVoiceInteraction, sources);} else {cancelAnimation();}} finally {Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);}return isAnimating();}protected void applyAnimationUnchecked(WindowManager.LayoutParams lp, boolean enter,int transit, boolean isVoiceInteraction,@Nullable ArrayList<WindowContainer> sources) {/*获取两个动画元素,一个用于普通动画,另一个用于缩略图动画*/final Pair<AnimationAdapter, AnimationAdapter> adapters = getAnimationAdapter(lp,transit, enter, isVoiceInteraction);/*普通动画*/AnimationAdapter adapter = adapters.first;/*缩略图动画*/AnimationAdapter thumbnailAdapter = adapters.second;if (adapter != null) {/*添加onAnimationFinished回调*/if (sources != null) {mSurfaceAnimationSources.addAll(sources);}/*在容器上启动动画*/startAnimation(getPendingTransaction(), adapter, !isVisible(),ANIMATION_TYPE_APP_TRANSITION);/*在动画期间需要显示壁纸 */            if (adapter.getShowWallpaper()) {getDisplayContent().pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;}/*启动缩略图动画*/  if (thumbnailAdapter != null) {mSurfaceFreezer.mSnapshot.startAnimation(getPendingTransaction(),thumbnailAdapter, ANIMATION_TYPE_APP_TRANSITION, (type, anim) -> { });}}}

(4)WindowContainer.getAnimationAdapter 获取远程/窗口/应用过渡动画

    Pair<AnimationAdapter, AnimationAdapter> getAnimationAdapter(WindowManager.LayoutParams lp,int transit, boolean enter, boolean isVoiceInteraction) {final Pair<AnimationAdapter, AnimationAdapter> resultAdapters;/*在动画期间窗口如何被堆栈边界裁剪*/final int appStackClipMode = getDisplayContent().mAppTransition.getAppStackClipMode();// Separate position and size for use in animators./*在动画期间的位置和大小*/final Rect screenBounds = getAnimationBounds(appStackClipMode);mTmpRect.set(screenBounds);getAnimationPosition(mTmpPoint);if (!sHierarchicalAnimations) {// Non-hierarchical animation uses position in global coordinates.mTmpPoint.set(mTmpRect.left, mTmpRect.top);}mTmpRect.offsetTo(0, 0);/*远程过渡动画*/final RemoteAnimationController controller =getDisplayContent().mAppTransition.getRemoteAnimationController();/*改变窗口的过渡动画*/final boolean isChanging = AppTransition.isChangeTransit(transit) && enter&& isChangingAppTransition();/*远程过渡动画,如通过Launcher3点击启动应用事,Launcher3会优先设置RemoteAnimationController*/// Delaying animation start isn't compatible with remote animations at all.if (controller != null && !mSurfaceAnimator.isAnimationStartDelayed()) {final Rect localBounds = new Rect(mTmpRect);localBounds.offsetTo(mTmpPoint.x, mTmpPoint.y);final RemoteAnimationController.RemoteAnimationRecord adapters =controller.createRemoteAnimationRecord(this, mTmpPoint, localBounds,screenBounds, (isChanging ? mSurfaceFreezer.mFreezeBounds : null));resultAdapters = new Pair<>(adapters.mAdapter, adapters.mThumbnailAdapter);/*改变窗口的过渡动画*/} else if (isChanging) {final float durationScale = mWmService.getTransitionAnimationScaleLocked();final DisplayInfo displayInfo = getDisplayContent().getDisplayInfo();mTmpRect.offsetTo(mTmpPoint.x, mTmpPoint.y);final AnimationAdapter adapter = new LocalAnimationAdapter(new WindowChangeAnimationSpec(mSurfaceFreezer.mFreezeBounds, mTmpRect,displayInfo, durationScale, true /* isAppAnimation */,false /* isThumbnail */),getSurfaceAnimationRunner());final AnimationAdapter thumbnailAdapter = mSurfaceFreezer.mSnapshot != null? new LocalAnimationAdapter(new WindowChangeAnimationSpec(mSurfaceFreezer.mFreezeBounds, mTmpRect, displayInfo, durationScale,true /* isAppAnimation */, true /* isThumbnail */), getSurfaceAnimationRunner()): null;resultAdapters = new Pair<>(adapter, thumbnailAdapter);mTransit = transit;mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();} else {/*是否需要创建 mAnimationBoundsLayer 来裁剪动画 */mNeedsAnimationBoundsLayer = (appStackClipMode == STACK_CLIP_AFTER_ANIM);/*装载合适的过渡动画*/final Animation a = loadAnimation(lp, transit, enter, isVoiceInteraction);if (a != null) {// Only apply corner radius to animation if we're not in multi window mode.// We don't want rounded corners when in pip or split screen.final float windowCornerRadius = !inMultiWindowMode()? getDisplayContent().getWindowCornerRadius(): 0;AnimationAdapter adapter = new LocalAnimationAdapter(new WindowAnimationSpec(a, mTmpPoint, mTmpRect,getDisplayContent().mAppTransition.canSkipFirstFrame(),appStackClipMode, true /* isAppAnimation */, windowCornerRadius),getSurfaceAnimationRunner());resultAdapters = new Pair<>(adapter, null);mNeedsZBoost = a.getZAdjustment() == Animation.ZORDER_TOP|| AppTransition.isClosingTransit(transit);mTransit = transit;mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();} else {resultAdapters = new Pair<>(null, null);}}return resultAdapters;}private Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,boolean isVoiceInteraction) {if (isOrganized()) {// Defer to the task organizer to run animationsreturn null;}/*显示信息*/final DisplayContent displayContent = getDisplayContent();final DisplayInfo displayInfo = displayContent.getDisplayInfo();final int width = displayInfo.appWidth;final int height = displayInfo.appHeight;ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM, "applyAnimation: container=%s", this);// Determine the visible rect to calculate the thumbnail clip with// getAnimationFrames./*  frame 进入动画结束或退出动画开始的边界。insets 被系统窗口覆盖的边界。stableInsets 确定稳定系统窗口覆盖的区域的边界。surfaceInsets 绘图表面和窗口内容之间的交集。*/final Rect frame = new Rect(0, 0, width, height);final Rect displayFrame = new Rect(0, 0,displayInfo.logicalWidth, displayInfo.logicalHeight);final Rect insets = new Rect();final Rect stableInsets = new Rect();final Rect surfaceInsets = new Rect();getAnimationFrames(frame, insets, stableInsets, surfaceInsets);/**/if (mLaunchTaskBehind) {// Differentiate the two animations. This one which is briefly on the screen// gets the !enter animation, and the other one which remains on the// screen gets the enter animation. Both appear in the mOpeningApps set.enter = false;}ProtoLog.d(WM_DEBUG_APP_TRANSITIONS,"Loading animation for app transition. transit=%s enter=%b frame=%s insets=%s "+ "surfaceInsets=%s",AppTransition.appTransitionToString(transit), enter, frame, insets, surfaceInsets);/*获取过渡动画,指向了AppTransition.loadAnimation,会单独开一小节分析源码*/final Configuration displayConfig = displayContent.getConfiguration();final Animation a = getDisplayContent().mAppTransition.loadAnimation(lp, transit, enter,displayConfig.uiMode, displayConfig.orientation, frame, displayFrame, insets,surfaceInsets, stableInsets, isVoiceInteraction, inFreeformWindowingMode(), this);if (a != null) {if (a != null) {// Setup the maximum app transition duration to prevent malicious app may set a long// animation duration or infinite repeat counts for the app transition through// ActivityOption#makeCustomAnimation or WindowManager#overridePendingTransition.a.restrictDuration(MAX_APP_TRANSITION_DURATION);}if (DEBUG_ANIM) {logWithStack(TAG, "Loaded animation " + a + " for " + this+ ", duration: " + ((a != null) ? a.getDuration() : 0));}final int containingWidth = frame.width();final int containingHeight = frame.height();/*设置动画的目标的尺寸以及目标的父项的尺寸来初始化。(支持相对于这些尺寸指定的动画尺寸)*/a.initialize(containingWidth, containingHeight, width, height);a.scaleCurrentDuration(mWmService.getTransitionAnimationScaleLocked());}return a;}

(5)AppTransition.loadAnimation 获取动画实例

    Animation loadAnimation(LayoutParams lp, int transit, boolean enter, int uiMode,int orientation, Rect frame, Rect displayFrame, Rect insets,@Nullable Rect surfaceInsets, @Nullable Rect stableInsets, boolean isVoiceInteraction,boolean freeform, WindowContainer container) {Animation a;/*锁屏消失时,进入应用界面的动画(包括两种,即将显示壁纸和不显示壁纸应用)*/if (isKeyguardGoingAwayTransit(transit) && enter) {a = loadKeyguardExitAnimation(transit);/*锁屏进入安全界面(紧急拨号,或者相机)时动画为无,一般此时动画由SystemUI处理*/} else if (transit == TRANSIT_KEYGUARD_OCCLUDE) {a = null;/*从安全界面进入锁屏的动画,针对的退出应用动画*/} else if (transit == TRANSIT_KEYGUARD_UNOCCLUDE && !enter) {a = loadAnimationRes(lp, com.android.internal.R.anim.wallpaper_open_exit);/*应用崩溃时动画为无*/} else if (transit == TRANSIT_CRASHING_ACTIVITY_CLOSE) {a = null;/*语音界面,进入前台时的动画*/} else if (isVoiceInteraction && (transit == TRANSIT_ACTIVITY_OPEN|| transit == TRANSIT_TASK_OPEN|| transit == TRANSIT_TASK_TO_FRONT)) {a = loadAnimationRes(lp, enter? com.android.internal.R.anim.voice_activity_open_enter: com.android.internal.R.anim.voice_activity_open_exit);ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,"applyAnimation voice: anim=%s transit=%s isEntrance=%b Callers=%s", a,appTransitionToString(transit), enter, Debug.getCallers(3));/*语音界面,退出时的动画*/} else if (isVoiceInteraction && (transit == TRANSIT_ACTIVITY_CLOSE|| transit == TRANSIT_TASK_CLOSE|| transit == TRANSIT_TASK_TO_BACK)) {a = loadAnimationRes(lp, enter? com.android.internal.R.anim.voice_activity_close_enter: com.android.internal.R.anim.voice_activity_close_exit);ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,"applyAnimation voice: anim=%s transit=%s isEntrance=%b Callers=%s", a,appTransitionToString(transit), enter, Debug.getCallers(3));/*Actiivty重新启动的动画,如配置修改时的重启*/} else if (transit == TRANSIT_ACTIVITY_RELAUNCH) {a = createRelaunchAnimation(frame, insets);ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,"applyAnimation: anim=%s nextAppTransition=%d transit=%s Callers=%s", a,mNextAppTransition, appTransitionToString(transit),Debug.getCallers(3));/*ActivityOptions(ANIM_CUSTOM)相关过渡动画 ,或者Actiivty.overridePendingTransition设置的过渡动画*/} else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CUSTOM) {a = loadAnimationRes(mNextAppTransitionPackage, enter ?mNextAppTransitionEnter : mNextAppTransitionExit);ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,"applyAnimation: anim=%s nextAppTransition=ANIM_CUSTOM transit=%s "+ "isEntrance=%b Callers=%s",a, appTransitionToString(transit), enter, Debug.getCallers(3));setAppTransitionFinishedCallbackIfNeeded(a);/*ActivityOptions 相关过渡动画*/} else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CUSTOM_IN_PLACE) {a = loadAnimationRes(mNextAppTransitionPackage, mNextAppTransitionInPlace);ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,"applyAnimation: anim=%s nextAppTransition=ANIM_CUSTOM_IN_PLACE "+ "transit=%s Callers=%s",a, appTransitionToString(transit), Debug.getCallers(3));/*ActivityOptions(ANIM_CLIP_REVEAL)相关过渡动画*/} else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CLIP_REVEAL) {a = createClipRevealAnimationLocked(transit, enter, frame, displayFrame);ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,"applyAnimation: anim=%s nextAppTransition=ANIM_CLIP_REVEAL "+ "transit=%s Callers=%s",a, appTransitionToString(transit), Debug.getCallers(3));/*ActivityOptions(ANIM_SCALE_UP)相关过渡动画*/} else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_SCALE_UP) {a = createScaleUpAnimationLocked(transit, enter, frame);ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,"applyAnimation: anim=%s nextAppTransition=ANIM_SCALE_UP transit=%s "+ "isEntrance=%s Callers=%s",a, appTransitionToString(transit), enter, Debug.getCallers(3));/*ActivityOptions(ANIM_THUMBNAIL_SCALE_UP/ANIM_THUMBNAIL_SCALE_DOWN)相关过渡动画*/} else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP ||mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN) {mNextAppTransitionScaleUp =(mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP);a = createThumbnailEnterExitAnimationLocked(getThumbnailTransitionState(enter),frame, transit, container);ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,"applyAnimation: anim=%s nextAppTransition=%s transit=%s isEntrance=%b "+ "Callers=%s",a,  mNextAppTransitionScaleUp? "ANIM_THUMBNAIL_SCALE_UP" : "ANIM_THUMBNAIL_SCALE_DOWN",appTransitionToString(transit), enter, Debug.getCallers(3));/*ActivityOptions(ANIM_THUMBNAIL_ASPECT_SCALE_UP/ANIM_THUMBNAIL_ASPECT_SCALE_DOWN)相关过渡动画*/} else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP ||mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN) {mNextAppTransitionScaleUp =(mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP);a = createAspectScaledThumbnailEnterExitAnimationLocked(getThumbnailTransitionState(enter), uiMode, orientation, transit, frame,insets, surfaceInsets, stableInsets, freeform, container);ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,"applyAnimation: anim=%s nextAppTransition=%s transit=%s isEntrance=%b "+ "Callers=%s",a, mNextAppTransitionScaleUp? "ANIM_THUMBNAIL_ASPECT_SCALE_UP": "ANIM_THUMBNAIL_ASPECT_SCALE_DOWN",appTransitionToString(transit), enter, Debug.getCallers(3));/*ActivityOptions(ANIM_OPEN_CROSS_PROFILE_APPS)相关过渡动画*/} else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_OPEN_CROSS_PROFILE_APPS && enter) {a = loadAnimationRes("android",com.android.internal.R.anim.task_open_enter_cross_profile_apps);ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,"applyAnimation NEXT_TRANSIT_TYPE_OPEN_CROSS_PROFILE_APPS: "+ "anim=%s transit=%s isEntrance=true Callers=%s",a, appTransitionToString(transit), Debug.getCallers(3));/*Activity WindowMode发生变化时,如自由模式变化为全屏模式*/} else if (transit == TRANSIT_TASK_CHANGE_WINDOWING_MODE) {// In the absence of a specific adapter, we just want to keep everything stationary.a = new AlphaAnimation(1.f, 1.f);a.setDuration(WindowChangeAnimationSpec.ANIMATION_DURATION);ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,"applyAnimation: anim=%s transit=%s isEntrance=%b Callers=%s",a, appTransitionToString(transit), enter, Debug.getCallers(3));} else {/* 见 frameworks/base/core/res/res/values/styles.xml*/int animAttr = 0;switch (transit) {case TRANSIT_ACTIVITY_OPEN:case TRANSIT_TRANSLUCENT_ACTIVITY_OPEN:animAttr = enter? WindowAnimation_activityOpenEnterAnimation: WindowAnimation_activityOpenExitAnimation;break;case TRANSIT_ACTIVITY_CLOSE:case TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE:animAttr = enter? WindowAnimation_activityCloseEnterAnimation: WindowAnimation_activityCloseExitAnimation;break;case TRANSIT_DOCK_TASK_FROM_RECENTS:case TRANSIT_TASK_OPEN:animAttr = enter? WindowAnimation_taskOpenEnterAnimation: WindowAnimation_taskOpenExitAnimation;break;case TRANSIT_TASK_CLOSE:animAttr = enter? WindowAnimation_taskCloseEnterAnimation: WindowAnimation_taskCloseExitAnimation;break;case TRANSIT_TASK_TO_FRONT:animAttr = enter? WindowAnimation_taskToFrontEnterAnimation: WindowAnimation_taskToFrontExitAnimation;break;case TRANSIT_TASK_TO_BACK:animAttr = enter? WindowAnimation_taskToBackEnterAnimation: WindowAnimation_taskToBackExitAnimation;break;case TRANSIT_WALLPAPER_OPEN:animAttr = enter? WindowAnimation_wallpaperOpenEnterAnimation: WindowAnimation_wallpaperOpenExitAnimation;break;case TRANSIT_WALLPAPER_CLOSE:animAttr = enter? WindowAnimation_wallpaperCloseEnterAnimation: WindowAnimation_wallpaperCloseExitAnimation;break;case TRANSIT_WALLPAPER_INTRA_OPEN:animAttr = enter? WindowAnimation_wallpaperIntraOpenEnterAnimation: WindowAnimation_wallpaperIntraOpenExitAnimation;break;case TRANSIT_WALLPAPER_INTRA_CLOSE:animAttr = enter? WindowAnimation_wallpaperIntraCloseEnterAnimation: WindowAnimation_wallpaperIntraCloseExitAnimation;break;case TRANSIT_TASK_OPEN_BEHIND:animAttr = enter? WindowAnimation_launchTaskBehindSourceAnimation: WindowAnimation_launchTaskBehindTargetAnimation;}a = animAttr != 0 ? loadAnimationAttr(lp, animAttr, transit) : null;ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,"applyAnimation: anim=%s animAttr=0x%x transit=%s isEntrance=%b "+ "Callers=%s",a, animAttr, appTransitionToString(transit), enter,Debug.getCallers(3));}return a;}Animation loadAnimationAttr(LayoutParams lp, int animAttr, int transit) {int resId = Resources.ID_NULL;Context context = mContext;/*依照包名从应用中获取过渡动画*/if (animAttr >= 0) {AttributeCache.Entry ent = getCachedAnimations(lp);if (ent != null) {context = ent.context;resId = ent.array.getResourceId(animAttr, 0);}}/*对透明Activity做特殊处理*/resId = updateToTranslucentAnimIfNeeded(resId, transit);/*加载过渡动画*/if (ResourceId.isValid(resId)) {return loadAnimationSafely(context, resId);}return null;}

注:系统内置动画frameworks/base/core/res/res/values/styles.xml

<!-- Standard animations for a full-screen window or activity. --><style name="Animation.Activity"><item name="activityOpenEnterAnimation">@anim/activity_open_enter</item><item name="activityOpenExitAnimation">@anim/activity_open_exit</item><item name="activityCloseEnterAnimation">@anim/activity_close_enter</item><item name="activityCloseExitAnimation">@anim/activity_close_exit</item><item name="taskOpenEnterAnimation">@anim/task_open_enter</item><item name="taskOpenExitAnimation">@anim/task_open_exit</item><item name="launchTaskBehindTargetAnimation">@anim/launch_task_behind_target</item><item name="launchTaskBehindSourceAnimation">@anim/launch_task_behind_source</item><item name="taskCloseEnterAnimation">@anim/task_close_enter</item><item name="taskCloseExitAnimation">@anim/task_close_exit</item><item name="taskToFrontEnterAnimation">@anim/task_open_enter</item><item name="taskToFrontExitAnimation">@anim/task_open_exit</item><item name="taskToBackEnterAnimation">@anim/task_close_enter</item><item name="taskToBackExitAnimation">@anim/task_close_exit</item><item name="wallpaperOpenEnterAnimation">@anim/wallpaper_open_enter</item><item name="wallpaperOpenExitAnimation">@anim/wallpaper_open_exit</item><item name="wallpaperCloseEnterAnimation">@anim/wallpaper_close_enter</item><item name="wallpaperCloseExitAnimation">@anim/wallpaper_close_exit</item><item name="wallpaperIntraOpenEnterAnimation">@anim/wallpaper_intra_open_enter</item><item name="wallpaperIntraOpenExitAnimation">@anim/wallpaper_intra_open_exit</item><item name="wallpaperIntraCloseEnterAnimation">@anim/wallpaper_intra_close_enter</item><item name="wallpaperIntraCloseExitAnimation">@anim/wallpaper_intra_close_exit</item><item name="fragmentOpenEnterAnimation">@animator/fragment_open_enter</item><item name="fragmentOpenExitAnimation">@animator/fragment_open_exit</item><item name="fragmentCloseEnterAnimation">@animator/fragment_close_enter</item><item name="fragmentCloseExitAnimation">@animator/fragment_close_exit</item><item name="fragmentFadeEnterAnimation">@animator/fragment_fade_enter</item><item name="fragmentFadeExitAnimation">@animator/fragment_fade_exit</item></style>

五.总结:

AppTransition是系统窗口动画的重要部分,是启动应用,退出应用,切换Activity的过渡动画的管理者。AppTransition不仅支持系统的过渡动画,也可以通过定制style或者Actiivty中overridePendingTransition的方式设置过渡动画,而且也支持远程动画(如Launcher3设置RemoteAnimationController)。AppTransition会把需要的动画交给SurfaceAnimationRunner作处理,而SurfaceAnimationRunner则通过Choreographer在vsync下一帧到来时启动过渡动画。

过渡动画过程为:
    (1)AppTransition.prepareAppTransitionLocked 确定基础的过渡动画类型
    (2)DisplayContent.executeAppTransition 申请执行过渡动画
    (3)WindowSurfacePlacer.performSurfacePlacement 获取过渡动画实例,添加至系统动画系统
        RootWindowContainer.checkAppTransitionReady
        AppTransitionController.handleAppTransitionReady
        AppTransitionController.applyAnimations
        WindowContainer.applyAnimation
        WindowContainer.applyAnimationUnchecked
            WindowContainer.getAnimationAdapter
                AppTransition.loadAnimation
            WindowContainer.startAnimation
                SurfaceAnimator.startAnimation
                LocalAnimationAdapter.startAnimation
                SurfaceAnimationRunner.startAnimation
    (4)SurfaceAnimationRunner.startPendingAnimationsLocked 通过Choreographer.postFrameCallback调用,开启动画

Android11 WMS 之 AppTransition相关推荐

  1. 家庭网络搭建_家庭网络

    家庭网络搭建 I spent some time overhauling my home network. There was no way I was going to settle for the ...

  2. Android6.0 WMS(八) 显示Activity的启动窗口

     在Android系统中,Activity组件在启动之后,并且在它的窗口显示出来之前,可以显示一个启动窗口.这个启动窗口可以看作是Activity组件的预览窗口,是由WindowManagerSe ...

  3. AppTransition

    前面的文章说过,AppTransition代表了activity组件的切换过程,其实解锁也是一种AppTrasition,只不过需要隐藏的activity组件是锁屏窗口罢了(严格来说并不是锁屏窗口被隐 ...

  4. geoserver安装_pgRouting教程九:使用GeoServer发布WMS/WFS接口

    本文衔接上篇文章: 不睡觉的怪叔叔:pgRouting教程八:使用pl/pgsql写存储过程​zhuanlan.zhihu.com 上篇文章使用pl/pgsql实现了存储过程,本文将使用GeoServ ...

  5. java wms open,OpenLayers - 调用WMS安全层

    我有一个asp.net Web应用程序来可视化地理服务器层 . 出于安全考虑,我在服务器端(C#)进行了身份验证,并使用从http://geoserverhost:8080/geoserver/j_s ...

  6. SAP WMS Posts

    This page contains SAP Related posts. The main topics will be from SAP EWM, SAP WM, SAP LE and SAP i ...

  7. .net 访问 geoserver 发布的 wms   跨域问题解决方案

    环境:  服务器  geoserver2.4.1 开发机访问服务器发布的wms 存在跨域问题,研究两天终于找到解决方案. 主要思路是: 使用jquery的ajax 代替Groserver的reques ...

  8. Cesium调用 WMS 、WMTS 服务

    参考文章地址:Cesium调用 ArcGIS Sever 以及 GeoSever 发布的地图服务 cesium测试示例(包括官方的示例)中   arcgis服务都无法访问了 根据原文找到一个在线的可访 ...

  9. 【转】GeoServer地图开发解决方案(四):发布Web地图服务(WMS)篇

    GeoServer 是 OpenGIS Web 服务器规范的 J2EE 实现的社区开源项目,利用 GeoServer 可以方便的发布地图数据,允许用户对特征数据进行更新.删除.插入操作,通过 GeoS ...

最新文章

  1. 【实用】一个移动端简单的UI弹窗组件,虽算不上高大上,但至少耐看
  2. 大厂也在用的 6种 数据脱敏方案,别做泄密内鬼
  3. python生产和消费模型_python queue和生产者和消费者模型
  4. java webservice 作用_@WebService这个标签的作用是什么
  5. linux识别fat16还是32,FAT16 、FAT32 、NTFS、LINUX区别.doc
  6. docker自定义端口挂载目录
  7. [Pku 2774] 字符串(六) {后缀数组的构造}
  8. Python NLP英文文本转小写
  9. 《Puppet实战手册》——2.5 使用标准的命名约定
  10. 基于XMLHttpRequest封装Ajax请求
  11. java messagebox_由MessageBox透视Win32 API的调用 | 学步园
  12. 【用C语言绘制谢尔宾斯基三角形】
  13. 快速学习Ant Design-简介
  14. CSDN(Markdown编辑)怎样打出各种表情符号和文章目录【图文】
  15. H5 video 自动播放(autoplay)不生效解决方案
  16. 攻防世界WEB题练习
  17. XGBoost Stopping to Avoid Overfitting(early_stopping_rounds )
  18. 城镇污水处理厂工艺概述及提标改造路线
  19. linux按目录名查找目录_如何在Linux中查找目录?
  20. PPG_Projector第一种方法:FindA

热门文章

  1. 区分: 间宾直宾(双宾语) 宾补(复合宾语)
  2. CREO枕头模型制作
  3. setenv与putenv的区别
  4. 一名优秀的产品经理,需要了解的数据分析模型
  5. html中计时器,计时器.html
  6. Maven命令行窗口指定settings.xml
  7. Python数据分析||基于逻辑回归的糖尿病视网膜病变的影响因素分析
  8. Linux ALSA声卡驱动之五:Machine 以及ALSA声卡的注册
  9. java毕业设计——基于java+Eclipse+jsp的网上手机销售系统设计与实现(毕业论文+程序源码)——网上手机销售系统
  10. 智能门锁APP让你的生活更智能