Android 理解requestStartTransition过渡动画

Android系统Shell过渡动画流程解析

摘要:本文详细分析了从Activity启动到Shell动画执行的完整流程。关键节点包括:1) ActivityStarter创建并收集Transition;2) 通过TransitionController将Transition请求发送到wm/shell进程;3) Shell端接收请求并执行动画;4) 动画完成后通知WMS使Activity进入RESUMED状态。流程涉及跨进程通信(通过ITransitionPlayer接口),并对比了传统过渡与Shell过渡的区别。核心控制点在TransitionController的requestStartTransition方法,该方法通过Binder调用将TransitionToken传递给Shell进程,触发后续动画执行。整个过程体现了Android窗口管理系统与Shell组件的协同工作机制。

启动动画到 wm/shell 的完整流程

复制代码
┌─────────────────────────────────────────────────────────────────────────────┐
│                   Activity 启动 → Shell动画 流程                             │
└─────────────────────────────────────────────────────────────────────────────┘

1️⃣ [ActivityStarter.executeRequest]  Line ~1510
    │
    │  创建Transition并开始收集
    ▼
    Transition newTransition = r.mTransitionController.createAndStartCollecting(TRANSIT_OPEN)
         │
         │  如果Shell Transitions启用,创建Transition
         │
         ▼
2️⃣ [ActivityStarter.startActivityInner]  Line 1875
    │
    │  执行启动逻辑,Activity被添加到Task
    │
    ▼
3️⃣ [ActivityStarter.handleStartResult]  Line 1732
    │
    │  核心:发送Transition到Shell
    ▼
    if (isIndependentLaunch && transition != null) {
        transitionController.requestStartTransition(transition, ...);
    }
         │
         │  ◄── 这里!Transition被发送到Shell!
         │
         ▼
4️⃣ [TransitionController.requestStartTransition]  Line 805
    │
    │  获取Shell的ITransitionPlayer代理
    ▼
    mTransitionPlayers.getLast().mPlayer.requestStartTransition(
            transition.getToken(),  // Transition token
            request);               // TransitionRequestInfo
         │
         │  ◄── 跨进程Binder调用到 wm/shell 进程
         │
         ▼
5️⃣ [Shell端 - ITransitionPlayer stub]
    │
    │  Shell接收Transition请求
    ▼
    TransitionPlaybackController 或 ShellTransitionPlayback
         │
         │  执行动画
         ▼
6️⃣ 动画完成 ──→ 通知WMS ──→ Activity变成RESUMED

创建Transition - ActivityStarter.java:1511-1512

复制代码
final Transition newTransition = r.mTransitionController.isShellTransitionsEnabled()
        ? r.mTransitionController.createAndStartCollecting(TRANSIT_OPEN) : null;

触发条件 :只有当 isShellTransitionsEnabled() 返回 true 时才使用 Shell Transitions

发送到Shell - ActivityStarter.java:1838-1842

复制代码
if (isIndependentLaunch && transition != null) {
    transitionController.requestStartTransition(transition,
            mTargetTask == null ? started.getTask() : mTargetTask,
            remoteTransition, null /* displayChange */);
}

触发条件 :

  • isIndependentLaunch - 独立启动(不是从属启动)

  • transition != null - Transition存在

Shell接收Transition - TransitionController.java:858-859

复制代码
mTransitionPlayers.getLast().mPlayer.requestStartTransition(
        transition.getToken(), request);

mTransitionPlayers 是 Shell 进程注册的 ITransitionPlayer 代理列表

完整时序图

复制代码
┌──────────────┐     ┌──────────────┐     ┌──────────────┐     ┌──────────────┐
│   App进程   │     │  system_server│     │  wm/shell   │     │ SurfaceFlinger│
│              │     │              │     │   进程       │     │              │
└──────┬───────┘     └──────┬───────┘     └──────┬───────┘     └──────┬───────┘
       │                    │                    │                    │
       │ startActivity()    │                    │                    │
       │───────────────────▶│                    │                    │
       │                    │                    │                    │
       │                    │ createAndStartCollecting(TRANSIT_OPEN)   │
       │                    │──────────┐          │                    │
       │                    │          │          │                    │
       │                    │◀─────────┘          │                    │
       │                    │                    │                    │
       │                    │ startActivityInner()│                    │
       │                    │  添加Activity到Task│                    │
       │                    │                    │                    │
       │                    │ requestStartTransition()                 │
       │                    │───────────────────▶│                    │
       │                    │                    │                    │
       │                    │                    │ 收到TransitionToken│
       │                    │                    │──────────┐         │
       │                    │                    │          │         │
       │                    │                    │◀─────────┘         │
       │                    │                    │                    │
       │                    │                    │ 执行动画...         │
       │                    │                    │───────────────────▶│
       │                    │                    │                    │
       │                    │                    │        动画显示     │
       │                    │                    │                    │
       │                    │◀───────────────────│ 动画完成            │
       │◀──────────────────│   onAnimationDone  │                    │
       │                    │                    │                    │
       │  Activity RESUMED │                    │                    │
       │                    │                    │                    │

Shell Transitions 架构

复制代码
┌─────────────────────────────────────────────────────────────────────────┐
│                     Shell Transitions 架构                               │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│  system_server (WMS)              │        wm/shell 进程                 │
│  ┌─────────────────────────┐     │    ┌─────────────────────────┐      │
│  │   TransitionController  │     │    │  TransitionPlayback     │      │
│  │                         │     │    │  Controller             │      │
│  │  • mTransitionPlayers   │─────┼───▶│  • requestStartTransition│      │
│  │  • mCollectingTransition│     │    │  • playAnimation        │      │
│  │  • mPlayingTransitions │     │    │  • onAnimationDone      │      │
│  └─────────────────────────┘     │    └─────────────────────────┘      │
│                                   │              │                      │
│  ┌─────────────────────────┐     │              ▼                      │
│  │   Transition            │     │    ┌─────────────────────────┐      │
│  │                         │     │    │  ShellTransitionModel   │      │
│  │  • mToken (IBinder)     │     │    │                       │      │
│  │  • mType (TRANSIT_OPEN) │     │    │  • WallpaperCanvas     │      │
│  │  • mSyncId              │     │    │  • RemoteAnimationRunner│      │
│  └─────────────────────────┘     │    └─────────────────────────┘      │
│                                   │              │                      │
└───────────────────────────────────┼──────────────┼──────────────────────┘
                                    │              │
                                    ▼              ▼
                         ┌─────────────────────────────────────┐
                         │        SurfaceFlinger               │
                         │                                     │
                         │  接收各层Surface,                  │
                         │  合成并输出到显示屏幕                 │
                         └─────────────────────────────────────┘

系统级开关 - WindowManagerService.java:450

复制代码
public static final boolean sEnableShellTransitions = getShellTransitEnabled();

Activity级别开关 - ActivityOptions

复制代码
// 通过ActivityOptions设置自定义动画
options.setRemoteTransition(remoteTransition);

// 或者使用自定义Transition
options.setTransitionOwners(remoteTransition);

Legacy vs Shell 对比

实际动画执行点

当你点击桌面图标启动一个App时:

复制代码
1. Launcher Activity 发起 startActivity()
        │
        ▼
2. ActivityStarter 创建 TRANSIT_OPEN 类型的 Transition
        │
        ▼
3. handleStartResult() 调用 requestStartTransition()
        │
        ▼
4. Binder 调用到 wm/shell 的 ITransitionPlayer
        │
        ▼
5. Shell 端的 TransitionPlaybackController 执行:
   ├── 计算动画参数(起始位置、结束位置、时长)
   ├── 创建动画Surface
   ├── 控制Surface显示/隐藏/变换
   └── 完成后通知WMS
        │
        ▼
6. 动画结束 → Activity变成RESUMED状态
相关推荐
q20609517101 小时前
文件上传漏洞攻防全解析
android
流星白龙1 小时前
【MySQL高阶】8.MySQL系统库
android·mysql·adb
Mr.QingBin1 小时前
android Surface绘制状态流转-WindowStateAnimator
android
码云骑士2 小时前
Android 应用启动过程
android
bqliang2 小时前
译 · Jake Wharton 访谈:Android 圈最熟悉的那个名字
android·程序员·开源
三少爷的鞋2 小时前
Android Data 层 Flow 最佳实践:以冷流为基础,按需转热,避免过早共享状态
android
私人珍藏库10 小时前
【Android】Soul v5.86.0 内置模块版
android·app·工具·软件·多功能
千里马学框架10 小时前
aosp新增窗口层级 Type 完整实现方案(有源码)-wms需求和面试题
android·智能手机·架构·wms·aaos·车机
峥嵘life16 小时前
Android 蓝牙设备连接广播详解-2026
android·python·学习