【Android 14源码分析】ShellTransitions总体流程介绍

2,243 阅读5分钟

忽然有一天,我想要做一件事:去代码中去验证那些曾经被“灌输”的理论。

                        -- 服装学院的IT男

ShellTransitions 在 Android 14 开始替代了之前的 AppTransition 正好最近遇到了相关问题,做一些简单的梳理。

建议阅读顺序:

BLASTSyncEngine设计剖析

ShellTransitions总体流程介绍

ShellTransitions-1-同步组初始化

ShellTransitions-2-requestStartTransition处理

ShellTransitions-3-动画前准备

ShellTransitions-4-播放动画与结束处理

1. 概述

“Shell”是处理人机交互的方式,而在安卓系统中 SystemUI 负责整个系统界面的显示和交互,所以 google 设计了个 “WMShell” 放在 SystemUI 端执行,比如最常见的分屏操作。 而窗口的核心处理逻辑还是在 system_server 端,称之为“WMCore”。

在 Android 14 中,google 将之前的 AppTransition 逻辑替换成了 ShellTransitions 。

AppTransition 的作用可以理解为负责 Activity 切换操作的过渡事务处理

之前分析过桌面冷启动应用的所有动画效果,其中就有 AppTransition 参与的动画(app_transition 类型动画),在 Android 14 中这部分的逻辑变为了 ShellTransitions ,执行动画的进程也由之前桌面执行远端动画变成了现在的由 SystemUI 执行动画。

后续的分析还是以冷启动为场景,对比的是之前版本的 AppTransition 逻辑,也就是“app_transition”动画。

其他类型的 Activity 切换场景总体思路也是类似的。

1.1 图层变化

在 Android 14 的版本中,冷启动应用动画开始时会出现"Transition Root: Task=XXX"图层,以前的动画图层名字为 “animation-leash of app_transition ”。 现在的图层的嵌套也和之前有区别,之前是动画图层下面只有新启动应用的 Task ,现在的版本则是把桌面的 Task 也挂载到下面了。

图层-动画开始出现root图层.png

随着动画的执行,发现"Transition Root: Task=XXX"动画图层并没有任何的变化,动画改变的是内部的 Task ,这点和以前也不同。

图层-动画进行-task改变.png

动画结束后,移除动画图层,恢复到动画前的层级关系,这步是一样的

图层-动画结束处理.png

经过这3张图可以看出来新版本动画还是有明细差别的,从视觉体现也很明显,Android 14 的动画就是简单的淡入移出,这个写个 APP 的人都知道,就是简单的 Activity 切换动画。 而之前 Android 13 的冷启动动画和 iPhone 一样是从桌面图标慢慢放大的效果。所以从视觉体验来说,我个人觉得 Android 14 反而不如之前。

当然最大的区别在于之前的动画是远端动画,在桌面进程播放,现在是在 SystemUI 播放。

1.2 总体流程

流程图-总体流程-ShellTransitions.png

可以看到一共有 2 次 WMCore -> WMShell 和 2次 WMShell -> WMCore 的操作。 流程从 system_server 开始,也在 system_server 结束。 动画的播放在 SystemUI 端 。

2.与同步引擎配合使用

这里说的同步引擎指的是 BLASTSyncEngine ,本来是服务于分屏逻辑的。分屏操作涉及到2个应用,为了避免显示异常,所以引入了 BLASTSyncEngine 来控制2个应用的 SurfaceControl.Transaction 一起提交。

在 Android 14 的版本中看到 BLASTSyncEngine 也被应用到了 ShellTransitions 中。

为了避免减少阅读困难,所以 ShellTransitions 的分析中封装了 BLASTSyncEngine 相关的逻辑,建议阅读本系列前先了解 BLASTSyncEngine的工作逻辑

3. 相关状态装类介绍

3.1 容器同步状态

# WindowState
    /** This isn't participating in a sync. */
    // 没有参与同步
    public static final int SYNC_STATE_NONE = 0;

    /** This is currently waiting for itself to finish drawing. */
    // 等待绘制
    public static final int SYNC_STATE_WAITING_FOR_DRAW = 1;

    /** This container is ready, but it might still have unfinished children. */
    // 此容器已准备就绪,但可能仍有未完成的子容器
    public static final int SYNC_STATE_READY = 2;

    @IntDef(prefix = { "SYNC_STATE_" }, value = {
            SYNC_STATE_NONE,
            SYNC_STATE_WAITING_FOR_DRAW,
            SYNC_STATE_READY,
    })
    @interface SyncState {}

3.2 过渡事务状态

# Transition

    /** The transition has been created but isn't collecting yet. */
    // 刚创建状态, 只是创建了过渡事务,但是还没开始收集
    private static final int STATE_PENDING = -1;

    /** The transition has been created and is collecting, but hasn't formally started. */
    // 过渡事务正在收集参与动画的容器,但动画尚未正式开始
    private static final int STATE_COLLECTING = 0;

    /**
     * The transition has formally started. It is still collecting but will stop once all
     * participants are ready to animate (finished drawing).
     */
    // 事务已经启动,但是还处于收集状态
    // 停止收集的条件是:所有参与者完成绘制(准备完毕)
    private static final int STATE_STARTED = 1;

    /**
     * This transition is currently playing its animation and can no longer collect or be changed.
     */
    // 已经开始播放过渡动画
    // 这种状态自然也不再收集了
    private static final int STATE_PLAYING = 2;

    /**
     * This transition is aborting or has aborted. No animation will play nor will anything get
     * sent to the player.
     */
    // 中止状态
    // 不再播放动画
    private static final int STATE_ABORT = 3;

    /**
     * This transition has finished playing successfully.
     */
    // 过渡动画播放完毕
    private static final int STATE_FINISHED = 4;

    @IntDef(prefix = { "STATE_" }, value = {
            STATE_PENDING,
            STATE_COLLECTING,
            STATE_STARTED,
            STATE_PLAYING,
            STATE_ABORT,
            STATE_FINISHED
    })
    @Retention(RetentionPolicy.SOURCE)
    @interface TransitionState {}

private @TransitionState int mState = STATE_PENDING;

4. 总体流程结束

调用链和流程图如下:

流程图-ShellTrnsition.png

堆栈:

ActivityStarter::startActivityUnchecked
    TransitionController::createAndStartCollecting
        Transition::init        -- 创建过渡事务 STATE_PENDING
        TransitionController::moveToCollecting  -- 设置为主事务  
            Transition::startCollecting   -- STATE_COLLECTING
                BLASTSyncEngine::startSyncSet -- 创建同步组
    TransitionController::collect
        Transition::collect
            BLASTSyncEngine::addToSyncSet -- 收集 ActivityRecord
            ChangeInfo::init
    ActivityStarter::startActivityInner
        ActivityStarter::getOrCreateRootTask
        ActivityStarter::setNewTask
            TransitionController::collectExistenceChange -- 记录 Task 存在性变化
                Transition::collect
                    BLASTSyncEngine::addToSyncSet -- 收集 Task
    ActivityStarter::handleStartResult
        TransitionController::collectExistenceChange -- 记录 ActivityRecord 存在性变化
            Transition::collect
        TransitionController::requestStartTransition  --  WMCore -> WMShell 第一次
            Transitions::requestStartTransition
                ActiveTransition::init
                TransitionHandler::handleRequest   -- 找到处理对应动画的TransitionHandler
                WindowOrganizer::startTransition   --    WMShell -> WMCore 第一次
                    WindowOrganizerController::startTransition
                        WindowOrganizerController::startTransition
                            Transition::start    -- STATE_STARTED
                                Transition::applyReady
                                    Transition::allReady
                                        BLASTSyncEngine::setReady
                                            SyncGroup::setReady   -- 设置同步组准备状态(false)
                mPendingTransitions::add

executeAppTransition 流程设置同步组准备就绪

RootWindowContainer::performSurfacePlacementNoTrace -- 检查直至同步完成
    BLASTSyncEngine::onSurfacePlacement
        Transition::onTransactionReady     -- STATE_PLAYING
            TransitionPlayerImpl::onTransitionReady -- WMCore -> WMShell 第二次
                Transitions::onTransitionReady
		    Transitions::processReadyQueue
			Transitions::playTransition
			    Transitions::dispatchTransition
				DefaultTransitionHandler::startAnimation
				    DefaultTransitionHandler::loadAnimation   -- 加载动画资源
				    DefaultTransitionHandler::buildSurfaceAnimation -- 构建动画
				    SurfaceControl.Transaction::apply   -- startTransaction
				    Animator::start  -- 开始动画
					DefaultTransitionHandler::applyTransformation
					Transitions::onFinish -- 动画结束
					    SurfaceControl.Transaction::apply   -- finishTransaction
					    WindowOrganizer::finishTransition   WMShell -> WMCore 第二次
						WindowOrganizerController::finishTransition
						    ransition::finishTransition  -- STATE_FINISHED

这个系列的文章目前只介绍了总体流程,一些细节还不清楚 google 为什么要这么做,所以这个系列后续会修订提高质量。

目前 ShellTransitions 的文章网上文章不多,所以先放出来,有意见的欢迎一起探讨。

参考链接:

juejin.cn/post/737171…

juejin.cn/post/739387…