【Android14 ShellTransitions】(一)开篇

说来惭愧,AndroidU都已经开发这么久了,但是我还没有整理过ShellTransition相关的知识。我本来希望能够系统的写一篇关于ShellTransition的笔记出来,但是发现一来这是一个比较庞大的模块,二来我个人能力有限,对ShellTransition目前掌握的并不透彻,只是朦胧上大体有一个认知。如果把ShellTransition的方方面面都了解清楚再去写这么一篇笔记,google说不定已经不用ShellTransition了,就像我刚刚弄清楚AppTransition和AppTransitionController这块的逻辑,AndroidU就把动画逻辑变成ShellTransition了一样,有点不讲武德了。所以趁ShellTransition还健在,我觉得还是趁热打铁吧,哪天看了ShellTransition的代码有点感悟了就去做相关记录,这样做的缺点就是知识点比较零散,写的会比较随意,并且也可能有理解的不到位的地方,但是希望可以靠后面的持续更新来慢慢改善这些不足,总比ShellTransition坟头草都三米高了才想起来要总结要好。

废话就到这里,现在开始吧。

ShellTransition相关类

网上关于ShellTransition的介绍还是比较少的,这个时候想要立刻能够对ShellTransition有一个大概认知,我一般会看注释,所以这里也是先看ShellTransition相关的类的注释。

1 TransitionController

首先是TransitionController,它有点像之前的AppTransitionController,是WMCore这边的动画的控制器调度器之类的,控制动画的生命周期。

另外一提,这里有一个WMCore和WMShell的新概念,似乎是和这些的类的包名有关,比如TransitionController这个类,它的目录为:

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

包名为:com.android.server.wm

它被归纳为WMCore里的。

而下面的Transitions类,它的目录为:

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

包名为:com.android.wm.shell.transition

它被归纳为WMShell里的。

好了,继续看TransitionController的注释:

java 复制代码
/**
 * 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.
 */
class TransitionController

处理记录(收集)和同步Transition的所有方面。 这仅涉及WM更改。 实际的动画由Player处理。

目前,一次只能有 1 个Transition成为主要"收集器"。 这是因为 WM 更改仍然以"全局"方式执行。 然而,收集实际上可以分为两个阶段:

  1. 实际进行WM更改并记录参与的容器。

  2. 等待参与容器准备就绪(例如重绘内容)。

因为 (2) 花费了大部分时间并且不会改变 WM,所以我们实际上可以在阶段 (2) 中同时进行多个Transition,同时在阶段 (1) 中进行一个Transition。 我们将这种安排称为"并行"收集,尽管实际上仍然只有 1 个Transition能够获得参与者。

当"主收集器"完成"设置"(第 1 阶段)并等待时,会发生并行收集。 此时,另一个Transition可以开始收集。 发生这种情况时,第一个Transition将移至"等待"列表,新Transition将成为"主收集器"。 如果在任何时候,"主收集器"在其中一个等待Transition之前开始播放,则第一个等待Transition将变回"主收集器"。 这维持了 WM 其余部分当前所期望的"全局"抽象。

当一个Transition移动到播放时,我们会根据所有其他播放Transition进行检查。 如果它不与它们重叠,它也可以并行动画。 在这种情况下,它将被分配一个新的"轨道"。 "轨道"是一种与Player沟通哪些Transition需要彼此串行播放的方式。 因此,如果我们发现一个Transition与一个轨道中的其他Transition重叠,则该Transition将被分配给该轨道。 但是,如果Transition与 大于1个轨道中的Transition重叠,我们实际上会将其标记为 SYNC,这意味着在所有先前的Transition动画完成之前它无法实际播放。 这是一种笨拙的做法,因为这是一种后备情况,支持更高级的东西会变得不必要的复杂。

2 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.
 */
public class Transitions

播放Transition动画。 在这个Players中,每个Transition都有一个生命周期。

  1. 当直接启动或请求Transition时,将其添加到"PENDING "状态。

  2. 一旦 WMCore 应用Transition并发出通知,Transition就会转至"READY "状态。

  3. 当Transition开始动画时,它会转至"ACTIVE "状态。

基本上:--start--> PENDING --onTransitionReady--> READY --play--> ACTIVE --finish--> --merge--> MERGED --

READY 及以后的生命周期按"轨道"进行管理。 在一个轨道中,所有动画都按描述的方式串行排列; 但是,多个轨道可以同时播放。 这意味着,在一个轨道内,一次只能有一个Transition处于动画状态("ACTIVE ")。

当一个Transition在一个轨道中进行动画时,分派到该轨道的Transition将以"READY "状态排队等待轮到。 同时,每当Transition到达"READY "队列的头部时,它将尝试与"ACTIVE "Transition合并。 如果合并成功,它将被移动到"ACTIVE "Transition的"合并"列表,然后下一个"READY "Transition可以尝试合并。 一旦"ACTIVE "过渡动画完成,就可以播放下一个"READY "Transition。

轨道分配预计由 WMCore 提供,这通常会尝试保持相同的分配。 但是,如果 WMCore 确定Transition与大于1个活动轨道冲突,则会将其标记为 SYNC。 这意味着在 SYNC Transition可以播放之前,必须刷新所有当前活动的轨道。

3 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

代表一个逻辑转换。这会跟踪与逻辑WM状态->状态转换相关的所有更改。

除了跟踪单个容器更改之外,这还跟踪排序更改(目前仅在顶部)。然而,由于顺序是一个"全局"属性,当转换并行收集时,顺序更改检测/报告的机制并不简单。

4 小结

看了注释其实还是挺懵b的,重点看下这块:

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

这里说下我个人的理解。

首先Transition是有一个状态集的:

  • STATE_PENDING,当Transition刚被创建的时候就是这个状态。
  • STATE_COLLECTING,当Transition开始收集动画参与者的时候,就会被置为这个状态。
  • STATE_STARTED,Transition已经被正式启动,它仍在收集中,但一旦所有参与者准备好进行动画(完成绘制),它将停止。结合STATE_COLLECTING,这里的意思应该就是说,如果Transition没有被start,那么它将一直处于收集参与者的状态,及时所有参与者都已经完成绘制可以开始动画了,但是因为当前Transition没有被启动,所以也无法进行下一步。
  • STATE_PLAYING,Transition正在执行动画,并且不能再继续收集了,也不能被改变。也就是说此时谁谁谁要执行动画已经确定了,并且这些参与者已经开始进行动画了,所以就不能再去收集新的参与者了,而且也不能对当前Transition进行修改了。
  • STATE_FINISHED,Transition已经成功执行完了动画。
  • STATE_ABORTED,Transition正在被中止或者已经中止,不会执行任何动画,也不会将任何内容发给player。

看到其实代码中是没有定义注释中说的那些READY、MERGED的状态的。

我们主要关注除STATE_ABORT的状态,既然是状态,那一般就是某段时间中Transition所处的一个状态,Transition一直处于这种状态,直到某个时间点发生了一些标志性事件,导致了Transition进入下一个状态。

1)、创建Transition,Transition的最初状态,STATE_PENDING状态。

2)、moveToCollecting,Transition进入STATE_COLLECTING状态。

3)、requestStartTransition,Transition进入STATE_STARTED状态。

4)、onTransitionReady,Transition进入STATE_PLAYING状态。

5)、finishTransition ,Transition进入STATE_FINISHED状态。

接下来我们以在Launcher界面点击App图标启动某个App为例,来分析一般过程,但是无法面面俱到,一些细节希望靠后续的系列文章可以补充。

相关推荐
恋猫de小郭22 分钟前
Flutter Widget Preview 功能已合并到 master,提前在体验毛坯的预览支持
android·flutter·ios
断剑重铸之日1 小时前
Android自定义相机开发(类似OCR扫描相机)
android
随心最为安1 小时前
Android Library Maven 发布完整流程指南
android
岁月玲珑1 小时前
【使用Android Studio调试手机app时候手机老掉线问题】
android·ide·android studio
还鮟6 小时前
CTF Web的数组巧用
android
小蜜蜂嗡嗡7 小时前
Android Studio flutter项目运行、打包时间太长
android·flutter·android studio
aqi007 小时前
FFmpeg开发笔记(七十一)使用国产的QPlayer2实现双播放器观看视频
android·ffmpeg·音视频·流媒体
zhangphil9 小时前
Android理解onTrimMemory中ComponentCallbacks2的内存警戒水位线值
android
你过来啊你9 小时前
Android View的绘制原理详解
android
移动开发者1号12 小时前
使用 Android App Bundle 极致压缩应用体积
android·kotlin