aosp15的窗口过渡动画ShellTransition相关的核心类整体介绍(1)

什么是ShellTransition

这里ShellTransition其实可以变成两部分,一个Shell和Transition,这里Shell大家可以简单认为代表是WMShell,而Transition就是普通的过渡的意思,这里Transition和以前的AppTransition中的Transition其实没有任何差别哈,都可以简单认为其实是一种App跳转的一种过渡,只不过差别如下:

AppTransition 整体都是在system_server进程自己独立完成,但是ShellTransition一般的会涉及system_server进程和systemui进程

为什么要用ShellTransition

针对这个为啥google原来的APPTransition用的好好的要全部升级到ShellTransition呢?这个问题的官方是没有看到相关的前后对比升级的原因,也只有确实使用认识了APPTransition和ShellTransition后自己可以有一些自己的见解,下面列出两个个人见解:

1、为wms核心业务进行解耦减负,ShellTransition本质也是为了减轻wms的业务,让wms只专注窗口相关的策略管理,这一点和分屏,自由窗口等慢慢剥离到WMShell一样

2、ShellTransition自带了同步引擎,同步刷新即让多个参与动画的窗口显示隐藏等在同一个Transaction事务中,这样可以减少一些因为时序关系导致的偶现显示疑难问题比如闪黑,闪屏等,提高系统稳定性。

高版本开放ShellTransition方法

这里看看aosp15是如何开放ShellTransition的
在老版本aosp13实际上使用是AppTransition,但是aosp15版本后发现
AppTransition的prepare方法会直接return

 boolean prepareAppTransition(@TransitionType int transit, @TransitionFlags int flags) {
        if (mDisplayContent.mTransitionController.isShellTransitionsEnabled()) {
            return false;
        }
}

这里看看mDisplayContent.mTransitionController.isShellTransitionsEnabled()方法
frameworks/base/services/core/java/com/android/server/wm/TransitionController.java

    boolean isShellTransitionsEnabled() {
        return !mTransitionPlayers.isEmpty();
    }

这里就是判断mTransitionPlayers有没有内容,那么这里的mTransitionPlayers又是来自哪里呢?
是在registerTransitionPlayer方法中

frameworks/base/services/core/java/com/android/server/wm/TransitionController.java

   void registerTransitionPlayer(@Nullable ITransitionPlayer player,
            @Nullable WindowProcessController playerProc) {
        if (!mTransitionPlayers.isEmpty()) {
            ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS_MIN, "Registering transition "
                    + "player %s over %d other players", player.asBinder(),
                    mTransitionPlayers.size());
            // flush currently running transitions so that the new player doesn't get
            // intermediate state
            flushRunningTransitions();
        } else {
            ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS_MIN, "Registering transition "
                    + "player %s ", player.asBinder());
        }
        mTransitionPlayers.add(new TransitionPlayerRecord(player, playerProc));
    }

frameworks/base/services/core/java/com/android/server/wm/WindowOrganizerController.java

@Override
public void registerTransitionPlayer(ITransitionPlayer player) {
    enforceTaskPermission("registerTransitionPlayer()");
    final int callerPid = Binder.getCallingPid();
    final int callerUid = Binder.getCallingUid();
    final long ident = Binder.clearCallingIdentity();
    try {
        synchronized (mGlobalLock) {
            final WindowProcessController wpc =
                    mService.getProcessController(callerPid, callerUid);
            mTransitionController.registerTransitionPlayer(player, wpc);
        }
    } finally {
        Binder.restoreCallingIdentity(ident);
    }
}

这里WindowOrganizerController的registerTransitionPlayer方法是systemui端负责调用的
frameworks/base/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java


   private void onInit() {
 //省略
        if (Transitions.ENABLE_SHELL_TRANSITIONS) {//一定要ENABLE_SHELL_TRANSITIONS
            mIsRegistered = true;
            // Register this transition handler with Core
            try {
                mOrganizer.registerTransitionPlayer(mPlayerImpl);//注册
            } catch (RuntimeException e) {
                mIsRegistered = false;
                throw e;
            }
            // Pre-load the instance.
            TransitionMetrics.getInstance();
        }
    }

看看这里的Transitions.ENABLE_SHELL_TRANSITIONS
frameworks/base/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java

/** Set to {@code true} to enable shell transitions. */
public static final boolean ENABLE_SHELL_TRANSITIONS = getShellTransitEnabled();

下面看看getShellTransitEnabled方法

    private static boolean getShellTransitEnabled() {
        try {
            if (AppGlobals.getPackageManager().hasSystemFeature(
                    PackageManager.FEATURE_AUTOMOTIVE, 0)) {//车载相关feature
                return SystemProperties.getBoolean("persist.wm.debug.shell_transit", true);
            }
        } catch (RemoteException re) {
            Log.w(TAG, "Error getting system features");
        }
        return true;//默认就是返回true
    }

getShellTransitEnabled方法可以看出默认情况下就是返回true,也就是开启ShellTransition

WMCore和WMShell概念

在学习ShellTransition时候首先要了解一下两个经常后续会说道的两个词:WMCore和WMShell
WMCore和WMShell的官方定义解释比较难找到哈,不过我这边看到有如下一段官方解释:

## Motivation

The primary motivation for the WindowManager Shell (WMShell) library is to effectively scale
WindowManager by making it easy™ and safe to create windowing features to fit the needs of
various Android products and form factors.

To achieve this, WindowManager separates the policy of managing windows (WMCore) from the
presentation of surfaces (WMShell) and provides a minimal interface boundary for the two to
communicate.

这里的官方解释了WMShell出现的动机,本质就是为了减轻原来wms的业务负担,可以更加安全创建一些窗口需求来满足各个产品,这里面就有出现对应的WMCore和WMShell,就可以看出两个名词的意义

WindowManager Shell ----》 简称 WMShell,一般在systemui进程

WindowManager的策略部分,即可以任务WindowManagerService那部分逻辑 —》 简称WMCore,其实就是system_server的wms

了解了WMCore和WMShell两个概念后,接下来就开始对相关的类进行深入的剖析

TransitionController(WMCore端过渡动画收集启动管理者)

先看看官方注释


/**
 * Handles all the aspects of recording (collecting) and synchronizing transitions. This is only
 * concerned with the WM changes. The actual animations are handled by the Player.
 *
 * Currently, only 1 transition can be the primary "collector" at a time. This is because WM changes
 * are still performed in a "global" manner. However, collecting can actually be broken into
 * two phases:
 *    1. Actually making WM changes and recording the participating containers.
 *    2. Waiting for the participating containers to become ready (eg. redrawing content).
 * Because (2) takes most of the time AND doesn't change WM, we can actually have multiple
 * transitions in phase (2) concurrently with one in phase (1). We refer to this arrangement as
 * "parallel" collection even though there is still only ever 1 transition actually able to gain
 * participants.
 *
 * Parallel collection happens when the "primary collector" has finished "setup" (phase 1) and is
 * just waiting. At this point, another transition can start collecting. When this happens, the
 * first transition is moved to a "waiting" list and the new transition becomes the "primary
 * collector". If at any time, the "primary collector" moves to playing before one of the waiting
 * transitions, then the first waiting transition will move back to being the "primary collector".
 * This maintains the "global"-like abstraction that the rest of WM currently expects.
 *
 * When a transition move-to-playing, we check it against all other playing transitions. If it
 * doesn't overlap with them, it can also animate in parallel. In this case it will be assigned a
 * new "track". "tracks" are a way to communicate to the player about which transitions need to be
 * played serially with each-other. So, if we find that a transition overlaps with other transitions
 * in one track, the transition will be assigned to that track. If, however, the transition overlaps
 * with transition in >1 track, we will actually just mark it as SYNC meaning it can't actually
 * play until all prior transition animations finish. This is heavy-handed because it is a fallback
 * situation and supporting something fancier would be unnecessarily complicated.
 */

注释内容比较多,只需要关心以下内容既可以:
负责处理同步过渡动画记录收集各方面,TransitionController只覆盖WM更改部分(简单说就是窗口相关的收集变化等),真正的动画播放还是Player(即WMShell)进行处理的。
目前,同一时间只能有一个transition可以成为主要“收集器”,因为WM变化以全局方式执行。然而,收集一般分为两个阶段:
1、实际进行WM更改并收集相关的参与容器
2、等待参与容器准备就绪(比如重新绘制内容)

其他的就暂时也不进行深入翻译,开始只需要知道上面两个步骤既可以。

Transitions(WMShell端过渡动画播放相关管理)

frameworks/base/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java

/**
 * Plays transition animations. Within this player, each transition has a lifecycle.
 * 1. When a transition is directly started or requested, it is added to "pending" state.
 * 2. Once WMCore applies the transition and notifies, the transition moves to "ready" state.
 * 3. When a transition starts animating, it is moved to the "active" state.
 *
 * Basically: --start--> PENDING --onTransitionReady--> READY --play--> ACTIVE --finish--> |
 *                                                            --merge--> MERGED --^
 *
 * The READY and beyond lifecycle is managed per "track". Within a track, all the animations are
 * serialized as described; however, multiple tracks can play simultaneously. This implies that,
 * within a track, only one transition can be animating ("active") at a time.
 *
 * While a transition is animating in a track, transitions dispatched to the track will be queued
 * in the "ready" state for their turn. At the same time, whenever a transition makes it to the
 * head of the "ready" queue, it will attempt to merge to with the "active" transition. If the
 * merge succeeds, it will be moved to the "active" transition's "merged" list and then the next
 * "ready" transition can attempt to merge. Once the "active" transition animation is finished,
 * the next "ready" transition can play.
 *
 * Track assignments are expected to be provided by WMCore and this generally tries to maintain
 * the same assignments. If, however, WMCore decides that a transition conflicts with >1 active
 * track, it will be marked as SYNC. This means that all currently active tracks must be flushed
 * before the SYNC transition can play.
 */

Transitions类主要就是播放过渡动画。在这个player中,每个transition对象都有一个自己生命周期。(transition就是过渡动画,这里不再翻译)
1、当一个transition直接启动或请求是,就会将他添加到“pending”状态
2、一旦WMCore应用了transition和通知出来,transition就会被移入到“ready”状态
3、当transition开始动画时,他就会被移入到“active”状态

上面都有提到状态,上面注释也有专门的状态链路,上状态如下情况:

--start--> PENDING --onTransitionReady--> READY --play--> ACTIVE --finish--> |
                                                --merge--> MERGED --^

注意这里看的时候要注意,小写字母这种代表是一个动作,比如start代表开始方法属于一个动作,动作会导致状态变成PENDING这种,这块后续再结合代码具体介绍方法和状态哈。

WMCore和WMShell代表过渡动画实体类

WMCore端的代表类:Transition
frameworks/base/services/core/java/com/android/server/wm/Transition.java

**
 * Represents a logical transition. This keeps track of all the changes associated with a logical
 * WM state -> state transition.
 * @see TransitionController
 *
 * In addition to tracking individual container changes, this also tracks ordering-changes (just
 * on-top for now). However, since order is a "global" property, the mechanics of order-change
 * detection/reporting is non-trivial when transitions are collecting in parallel. See
 * {@link #collectOrderChanges} for more details.
 */
class Transition implements BLASTSyncEngine.TransactionReadyListener {
    private static final String TAG = "Transition";
    private static final String TRACE_NAME_PLAY_TRANSITION = "playing";

    /** The default package for resources */
    private static final String DEFAULT_PACKAGE = "android";

    /** 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;

Transition是过渡动画在WMCore的代表类,它主要保持跟踪这WM状态到过渡动画状态,即最后状态都会体现在这个Transition类中的几个状态,默认状态是STATE_PENDING。

WMShell端的过渡动画实体类:ActiveTransition类位于Transitions.java下面
frameworks/base/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java

private static final class ActiveTransition {
        final IBinder mToken;

        TransitionHandler mHandler;
        boolean mAborted;
        TransitionInfo mInfo;
        SurfaceControl.Transaction mStartT;
        SurfaceControl.Transaction mFinishT;

        /** Ordered list of transitions which have been merged into this one. */
        private ArrayList<ActiveTransition> mMerged;

        ActiveTransition(IBinder token) {
            mToken = token;
        }
//省略

这里没看到对ActiveTransition进行注释说,这里因为很多核心逻辑是在ActiveTransition成员变量TransitionInfo中,这里大家先简单知道ActiveTransition是WMShell端的过渡动画对象与WMCore端的Transition对象靠mToken进行对应。

WMCore和WMShell端主要核心类关系及作用总结图:

核心类即职责图

文章来源参考:
https://mp.weixin.qq.com/s/ZBKZ6YOzZrRCltgR0FSqxA

更多framework实战干货,请关注下面“千里马学框架”

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千里马学框架

帮助你了,就请我喝杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值