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状态
相关推荐
帅次1 小时前
Android 高级工程师面试:Flutter Widget 体系 近1年高频追问 20 题
android·flutter·面试·element·widget·setstate·renderobject
帅次1 小时前
Android 高级工程师面试:Jetpack 核心 近1年高频追问 20 题
android·面试·协程·jetpack·stateflow·lifecycle
爱笑鱼2 小时前
Handler(四):Handler 卡顿怎么定位?从 Slow delivery 到 Slow dispatch
android
九皇叔叔2 小时前
RHEL9.8 配置本地镜像仓库
android·java·缓存
私人珍藏库3 小时前
[Android] 聊天记录微备份 -聊天记录备份+本地数据备份
android·人工智能·app·软件·多功能
私人珍藏库4 小时前
[Android] PocketPal -本地离线AI助手+大模型部署神器
android·人工智能·app·软件·多功能
listening7774 小时前
HarmonyOS 6.1 跨端实战:用ArkUI-X把电商App同时跑在Android/iOS上
android·ios·harmonyos
爱笑鱼4 小时前
Handler(三):主线程、HandlerThread、Binder 线程到底怎么区分?
android
w139548564224 小时前
鸿蒙实战:报告与雷达图 ReportDao
android·华为·harmonyos·鸿蒙系统
爱笑鱼5 小时前
Handler(二):MessageQueue 为什么不是普通队列?
android