Activity 启动的整体流程与第一个阶段解读参数

Activity 的启动过程是 Android Framework 中最复杂的流程之一,它涉及多个进程间的通信(IPC)。

1. 启动流程涉及的四个角色

  1. Launcher 进程或 App 进程:发起启动 Activity 的请求(通过 startActivity)。
  2. **System_Server 进程 (AMS)**:核心控制中心。负责解析 Intent、管理 Activity 栈(Task/Stack)、权限检查等。
  3. Zygote 进程:孵化器。如果目标 App 进程尚未启动,AMS 会请求 Zygote Fork 出一个新的进程。
  4. 目标 App 进程:Activity 最终运行的地方。在 ActivityThread 中完成初始化并回调 onCreate

2. 第一阶段:从 App 到 AMS 的跳转

当我们在代码中调用 startActivity(intent) 时,实际上经历了一系列的“套路”:

2.1 ContextImpl.startActivity

所有的 Context 子类(Activity, Service 等)最终都会调用到 ContextImpl 的实现中。

2.2 Instrumentation.execStartActivity

Instrumentation 是 Activity 的“管家”,负责监控 App 与系统的所有交互。在这里,它会通过 ActivityTaskManager.getService() 获取到 IActivityTaskManager 的 Binder 代理对象。

2.3 跨进程调用 (IPC)

通过 Binder 机制,请求从当前进程“跳”到了 System_Server 进程中的 ActivityTaskManagerService (ATMS)。


3. 核心参数解读

在进入 AMS 内部前,有几个关键概念必须厘清:

  • ActivityRecord:在 AMS 端,每一个 Activity 实例都对应一个 ActivityRecord 对象,它记录了该 Activity 的所有信息。
  • TaskRecord:任务栈。一个 Task 可以包含多个 Activity,遵循后进先出(LIFO)原则。
  • ActivityStack:管理 Task 的层级结构。

4. 源码关键点 (API 29+)

在 Android 10 以后,Activity 的启动逻辑从 ActivityManagerService 大量迁移到了 ActivityTaskManagerService

1
2
3
4
5
6
7
8
// ATMS 端的入口方法
@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho,
int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
// ... 调用执行链
return startActivityAsUser(...);
}

接下来的文档中,我们将详细解析 ActivityStarter 如何处理 Flag 以及如何决定 Activity 该落入哪个 Task。

Activity 生命周期事务封装 (ClientTransaction)

在 Android 8.0 之后,系统引入了 ClientTransaction 机制来重构 Activity 的生命周期管理。这是一种基于“事务”的设计模式,将原本散落在 AMS 中的各种生命周期指令进行了统一封装。

1. 为什么需要事务封装?

在旧版本中,AMS 直接调用应用进程的 IApplicationThread 接口(如 scheduleLaunchActivity)。这种方式扩展性差,且难以处理复杂的复合状态切换。
引入事务后,AMS 只需要发送一个 ClientTransaction,其中包含了:

  • Callback:如 LaunchActivityItem(创建 Activity)。
  • FinalState:如 ResumeActivityItem(最终状态)。

2. 核心组件

  • ClientTransaction:事务容器。
  • ClientTransactionHandler:在应用进程中(通常是 ActivityThread)负责执行事务。
  • TransactionExecutor:事务执行器,负责按照正确的逻辑顺序(例如先 Create 再 Resume)调度事务中的各项指令。

3. 生命周期执行链路

  1. AMS 服务端:创建 ClientTransaction,并添加对应的生命周期 Item。
  2. 跨进程传递:通过 IApplicationThread.scheduleTransaction 发送到目标 App 进程。
  3. App 客户端ActivityThread 收到后,交给 TransactionExecutor 执行。
  4. 执行逻辑
    • executeCallbacks():执行如 LaunchActivityItem 等初始化操作。
    • executeLifecycleState():执行如 ResumeActivityItem 等状态变更操作。

4. 总结

生命周期事务封装是 Android 系统现代化的重要体现。它不仅让 AMS 的逻辑更加简洁,也为后续的 多窗口模式折叠屏 复杂状态切换提供了坚实的底层架构支持。

WMS 源代码流程分析

本指南将从源代码角度分析 WindowManagerService (WMS) 的核心工作流程,并配合时序图进行说明。

1. WMS 的启动与初始化 (SystemServer)

WMS 是在 SystemServer 进程中启动的系统核心服务。

  • 路径: frameworks/base/services/java/com/android/server/SystemServer.java
  • 代码关键点:
    1
    2
    3
    // 在 startOtherServices 方法中
    wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore, new PhoneWindowManager(), mActivityManagerService.getAppTransition());
    ServiceManager.addService(Context.WINDOW_SERVICE, wm);

2. 窗口添加流程 (WindowManager.addView)

这是应用进程请求 WMS 显示 UI 的核心路径。

2.1 时序图:addView 过程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
sequenceDiagram
participant App as 应用进程 (Activity/View)
participant WMGlobal as WindowManagerGlobal
participant VRI as ViewRootImpl
participant Session as Session (WMS Proxy)
participant WMS as WindowManagerService

App->>WMGlobal: addView(view, params)
WMGlobal->>VRI: new ViewRootImpl()
VRI->>VRI: setView()
VRI->>Session: addToDisplay()
Session->>WMS: addWindow()
WMS->>WMS: 验证权限 & Token
WMS->>WMS: 创建 WindowState 实例
WMS-->>VRI: 返回操作结果 (OK/Err)

2.2 核心步骤解析

  1. WindowManagerGlobal: 应用进程内的单例,管理所有窗口的 View 和 ViewRootImpl。
  2. ViewRootImpl: 连接 WindowManager 和控制台的纽带,负责触发绘制和与 WMS 通信。
  3. Session: 每个应用进程在 WMS 中对应一个 Session 对象,用于跨进程通信。
  4. addWindow: WMS 内部方法,负责创建 WindowState 并维护 Z-order 堆栈。

3. 布局与 Surface 分配 (Relayout)

窗口添加后,需要确定具体大小并获得绘图“画布”(Surface)。

3.1 时序图:Relayout 过程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
sequenceDiagram
participant VRI as ViewRootImpl
participant Session as Session (WMS Proxy)
participant WMS as WindowManagerService
participant WinState as WindowState
participant SF as SurfaceFlinger

VRI->>VRI: performTraversals()
VRI->>Session: relayout()
Session->>WMS: relayoutWindow()
WMS->>WinState: createSurfaceControl()
WinState->>SF: 请求分配 Layer
SF-->>WinState: 返回 SurfaceControl Native 句柄
WMS-->>VRI: 填充应用端的 Surface 对象
VRI->>VRI: 开始应用层绘制 (Canvas/OpenGL)

4. 关键类及其关系

类名 职责
IWindowSession App -> WMS 的单向通道,处理添加、删除、布局请求。
IWindow WMS -> App 的回调通道,处理窗口缩放、焦点变化等。
WindowState WMS 为每个窗口维护的“身份证”,包含位置、层级、可见性等。
WindowToken 窗口的归类令牌,用于管理 Activity 或 Dialog 等一组窗口的生命周期。
DisplayContent 对应一个物理屏幕,管理该屏幕下的所有窗口堆栈。

5. 总结

WMS 的核心逻辑在于 管理协调

  • 管理: 维护窗口的大小、位置、层级(Z-Order)。
  • 协调: 向上承接 View 系统(App),向下通过 SurfaceFlinger 申请显示资源,同时与 InputManagerService 协作分发触摸事件。

AMS 与 ATMS 的区别解析

自 Android 10 (API 29) 开始,Google 对原本庞大的 ActivityManagerService (AMS) 进行了结构性重构,将其核心的 Activity 管理职能抽离出来,成立了 ActivityTaskManagerService (ATMS)。

1. 为什么要进行拆分?

在早期的 Android 版本中,AMS 承载了太多的职责。这种“巨石”设计导致了严重的工程问题:

核心痛点 详细解析与举例
代码耦合严重 现象:Activity 栈管理逻辑与广播分发逻辑共用同一个线程/锁。
举例:在计算复杂的 Task 切换(如分屏模式下的 Activity 移动)时,如果逻辑出错产生死锁或耗时过长,会直接阻塞同一进程内的广播分发 Handler,导致无关的广播接收者出现 ANR。
职责不清晰 现象:WMS 需要频繁跨模块获取 Activity 状态。
举例:WMS 在准备窗口切换动画时,必须知道 Activity 是否可见。旧版 WMS 需通过繁琐的 IPC 调用 AMS 的 ActivityRecord 状态,这不仅产生了大量的跨模块冗余代码,还增加了同步状态时的延迟。拆分后,ATMS 与 WMS 深度融合,共同管理 WindowContainer 层级结构。
维护成本极高 现象:单文件行数爆炸,合并冲突不断。
举例ActivityManagerService.java 的源码量曾一度突破 30,000 行。开发者 A 在修复 Service 粘性启动的 Bug,开发者 B 在优化 Activity 的启动速度,由于两人都在操作同一个文件,导致每次版本合并时都会产生极其复杂的代码冲突。

核心管理对象:Record 体系

为了实现职责分离,AMS 与 ATMS 分别维护了不同的核心数据对象:

对象名称 所属服务 核心职责
ProcessRecord AMS 进程管家。描述一个应用进程的实体,记录了进程的 PID、UID、包含的组件(Service, Receiver)、进程优先级(Adj)以及内存状态。AMS 通过它来决定系统内存不足时该“杀掉”哪个进程。
ActivityRecord ATMS Activity 档案。描述一个 Activity 实例的最小单位。记录了 Intent、所属 Task、状态(Resumed, Paused 等)、对应的 WindowToken。它与应用端的 Activity 实例一一对应。
TaskRecord ATMS 任务容器。描述一个“最近任务”或“任务栈”。管理一组相关的 ActivityRecord,决定了 Activity 的回退顺序(LIFO,后进先出)以及在多窗口模式下的显示分组。

2. AMS vs ATMS 职责对比

维度 ActivityManagerService (AMS) ActivityTaskManagerService (ATMS)
核心职责 管理应用生命周期(进程、四大组件中的后三者)。 专门管理 Activity 及其容器(Task, Stack, Display)。
组件管理 Service, BroadcastReceiver, ContentProvider。 Activity 启动、生命周期、Task 切换。
进程管理 负责 OOM Adjuster、进程启动与回收。 不直接参与进程管理。
交互对象 主要与 ProcessRecord 交互。 主要与 ActivityRecordTaskRecord 交互。
WMS 关系 间接交互。 强绑定。与 WMS 共同管理窗口 and Activity。

3. 架构演进的关键点

3.1 跨进程通信的变化

  • Android 9 以前:App -> AMS (startActivity)。
  • Android 10 以后:App -> ATMS (startActivity)。

3.2 内部协作流程

  1. ATMS 负责判断 Activity 应该在哪个 Task 启动,并管理其生命周期状态。
  2. 当需要启动一个新的进程来承载 Activity 时,ATMS 会回调 AMSstartProcessAsync 方法。
  3. AMS 负责与 Zygote 通信并完成进程的创建。

4. 总结:一句话区分

  • ATMS 是“Activity 管家”:只关心 Activity 怎么跳、怎么显示、怎么分组。
  • AMS 是“应用管家”:关心进程还在不在、Service 跑没跑、广播发没发。

这种拆分使得 Android 系统在支持 多窗口模式 (Multi-Window)折叠屏 (Foldables) 时,逻辑更加清晰和独立。

Handler 与 ActivityThread 的协作机制

在 AMS 管理 Activity 生命周期的过程中,Handler 扮演了“线程切换器”的关键角色。理解 ActivityThread 如何通过 Handler 接收并执行来自 AMS 的指令,是掌握 Framework 通信模型的核心。

1. 协作模型:从 Binder 线程到主线程

AMS 运行在 system_server 进程中,通过 IApplicationThread (Binder 接口) 向应用进程发送指令。

步骤 运行环境 执行动作
1. 跨进程调用 Binder 线程池 应用进程收到 AMS 的 Binder 调用(如 scheduleTransaction)。
2. 线程切换 Handler 发送消息 Binder 线程不直接操作 UI,而是将任务通过 H (Handler) 发送到主线程。
3. 消息排队 MessageQueue 任务作为 Message 进入主线程的消息队列,遵循优先级排序。
4. 执行任务 主线程 (Looper) Looper 取出消息并回调 handleMessage,最终执行 Activity 的生命周期。

2. ActivityThread 内部的管家:类 H

ActivityThread 源码中,定义了一个内部类 H,它继承自 Handler。它是应用进程中最重要的消息处理中心。

核心消息常量 (Message Type) 对应场景
EXECUTE_TRANSACTION Android 9.0+ 引入,统一处理绝大多数生命周期事务(Start, Resume 等)。
BIND_APPLICATION 应用进程启动后的初始化指令。
EXIT_APPLICATION 请求应用退出。
RECEIVER 广播处理指令。
1
2
3
4
5
6
7
8
9
10
11
12
// ActivityThread.java 中的内部类 H
class H extends Handler {
public void handleMessage(Message msg) {
switch (msg.what) {
case EXECUTE_TRANSACTION:
final ClientTransaction transaction = (ClientTransaction) msg.obj;
mTransactionExecutor.execute(transaction);
break;
// ... 其他消息处理
}
}
}

3. 同步屏障 (Sync Barrier) 在 AMS 场景下的应用

当 AMS 请求启动一个 Activity 或执行渲染任务时,为了保证 UI 能够以 60fps/120fps 的频率流畅刷新,系统会使用同步屏障机制。

概念 作用机制 在 AMS 场景的应用
插入屏障 MessageQueue 头部插入一个 target 为空的特殊消息。 Choreographer 接收到 VSync 信号,或者 AMS 触发界面刷新时发送。
优先异步 此时 Looper 会跳过普通消息,只执行标记为 isAsynchronous 的消息。 确保 UI 绘制任务、某些关键生命周期事务不会被队列中积压的普通消息(如日志、数据上报)阻塞。
移除屏障 渲染完成后移除,恢复普通消息的处理。 保证系统吞吐量与 UI 流畅度的平衡。

4. 总结:为什么要通过 Handler?

  1. 线程安全:Android 的 UI 控件是非线程安全的,必须保证所有对 Activity 状态的修改都在主线程完成。
  2. 异步缓冲:AMS 往往是“发后即忘”的异步调用。Handler 提供的消息队列可以缓冲来自系统的密集请求,防止应用进程因瞬间过载而崩溃。
  3. 优先级调度:配合同步屏障,Handler 机制能确保最重要的“显示”任务永远被优先执行。

ActivityThread 接收并处理 AMS 指令全过程

在 Android 的系统架构中,AMS(System Server 进程)与 ActivityThread(应用进程)之间的通信是典型的 C/S 架构。AMS 作为服务端下发指令,ActivityThread 作为客户端接收并执行。

1. 通信架构:Binder 边界

AMS 并不直接持有 ActivityThread 对象,而是通过 IApplicationThread 这一 Binder 接口进行通信。

角色 实现类 物理位置 职责
Binder 服务端 ActivityThread.ApplicationThread 应用进程 继承自 IApplicationThread.Stub,开启 Binder 线程池等待调用。
Binder 代理端 ApplicationThreadProxy System Server 进程 AMS 持有该代理,用于向 App 进程发送指令。

2. 指令接收流程:从 Binder 线程到主线程

当 AMS 发起一个指令(如启动 Activity)时,数据流转如下:

第一步:Binder 线程接收

AMS 调用 app.thread.scheduleTransaction(transaction)。此时,App 进程中的 Binder 线程池 会随机选择一个线程来执行 ApplicationThread 对应的接口方法。

第二步:向主线程分发

由于 Binder 线程不能直接操作 UI 或执行 Activity 生命周期,ApplicationThread 会通过内部类 H(Handler)将任务发送到主线程。

1
2
3
4
5
// ActivityThread.java 内部代码逻辑
public void scheduleTransaction(ClientTransaction transaction) {
// 这里的 this 指向 H (Handler)
sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
}

第三步:主线程消息循环 (Looper)

主线程的 Looper 不断从 MessageQueue 中取出消息。当收到 EXECUTE_TRANSACTION 时,回调 HhandleMessage

第四步:执行具体逻辑

对于生命周期相关的指令,ActivityThread 会委派给 TransactionExecutor 执行,最终调用到 ActivityonCreate/onStart 等方法。


3. 核心处理中心:类 H

ActivityThread 内部维护的 Handler H 是所有系统指令的汇聚点。它处理的消息类型决定了应用的行为。

关键消息 (What) 来源与作用
BIND_APPLICATION AMS 要求进程进行初始化(创建 Application, 加载 Provider)。
EXECUTE_TRANSACTION Android 9.0+ 引入,聚合了几乎所有生命周期回调(Launch, Resume, Stop 等)。
RECEIVER 处理非动态注册的广播接收者。
SERVICE_ARGS 启动或分发 Service 任务。

4. 协作机制总结

关键环节 核心机制 核心目的
跨进程传输 Binder 实现 System Server 与 App 进程的通信边界。
线程切换 Handler (类 H) 将异步的系统指令切换到单线程的 UI 线程执行,确保线程安全。
顺序保证 MessageQueue 确保来自系统的多个指令(如先 Create 后 Resume)按序执行。
事务封装 ClientTransaction 在现代 Android 版本中简化生命周期管理,支持复杂的组合状态切换。

💡 面试要点:

  1. ActivityThread 的主线程循环是什么?
    答:是 Looper.loop(),它不仅处理用户交互,还处理来自 AMS 的所有生命周期指令。
  2. 为什么 ApplicationThread 里的方法不直接改 UI?
    答:因为 ApplicationThread 的方法运行在 Binder 线程 中,而 Android 的 UI 系统是非线程安全的,必须通过 Handler 切换到主线程。
  3. Handler H 的作用?
    答:它是应用进程的“神经中枢”,负责将系统的异步调用同步化到主线程执行。

Activity 启动之栈管理与 LaunchMode 判定

当 Activity 的启动请求进入 ATMS 后,最核心的逻辑就是:这个 Activity 应该放在哪个任务栈(Task)里? 这涉及到对 LaunchMode、Intent Flags 以及 TaskAffinity 的综合判定。

1. 核心角色:ActivityStarter

ActivityStarter 是启动流程中的“决策者”。它负责解析启动参数,并调用 startActivityUnchecked 开始处理栈逻辑。

2. LaunchMode 与 栈分配逻辑表

启动模式 ATMS 的核心逻辑 典型表现
standard 不做检查,直接创建新实例。 每次启动都会压入当前栈顶。
singleTop 检查目标栈顶。若已是该实例,回调 onNewIntent 防止栈顶重复创建。
singleTask 在全局寻找是否存在对应 taskAffinity 的栈。若有则移至前台并清理其上方所有 Activity (Clear Top)。 确保一个任务栈中只有一个实例。
singleInstance 强制创建一个新的任务栈,且该栈只能有这一个实例。 独占一个任务栈(如电话界面)。

3. Intent Flags 的影响

代码中通过 Intent.setFlags() 设置的参数优先级高于 XML 定义。

  • FLAG_ACTIVITY_NEW_TASK:对应 singleTask 的基本行为,寻找或创建新栈。
  • FLAG_ACTIVITY_CLEAR_TOP:如果栈中已存在该实例,销毁其上的所有 Activity。
  • FLAG_ACTIVITY_REORDER_TO_FRONT:将已存在的实例移到栈顶,不销毁中间的 Activity。

4. 栈管理的关键步骤

  1. findTask:根据 taskAffinityFlags 寻找匹配的 TaskRecord
  2. computeStack:确定目标 Activity 应该落在哪个 ActivityStack(在 Android 10+ 主要是 DisplayContent 下的容器)。
  3. resumeFocusedStacksTopActivities:将目标栈移到最前台,准备执行显示逻辑。

5. 调试技巧

使用以下命令可以实时观察栈的变化,这是理解栈管理逻辑的“神技”:

1
adb shell dumpsys activity activities

关注点: 寻找 TaskRecord 节点,查看其内部的 ActivityRecord 列表及其 intent 信息。

Activity 启动之进程创建流程(AMS 与 Zygote 的握手)

在启动 Activity 时,如果 ATMS 发现目标进程(ProcessRecord)不存在,就会触发进程创建流程。这是 Android 系统中典型的“按需启动”机制。

1. 触发点:AMS.startProcessLocked

当 ATMS 判定需要新进程来承载 Activity 时,会跨模块回调 AMS:

1
2
3
4
5
// 核心逻辑简述
if (app == null) {
// 进程不存在,开始启动进程
mService.startProcessLocked(processName, info, ...);
}

2. AMS 与 Zygote 的通信流程表

阶段 核心方法 动作描述
1. 决策 startProcessLocked AMS 确定进程参数(UID, GID, 启动类 ActivityThread)。
2. 发起请求 Process.start 通过 ZygoteProcess 建立与 Zygote 的 Socket 连接。
3. 通信 ZygoteState.connect /dev/socket/zygote 写入启动参数字符串。
4. 孵化 Zygote.fork() Zygote 接收信号,Fork 自身进程(利用 COW 机制)。
5. 诞生 RuntimeInit 子进程初始化运行环境,并抛出 MethodAndArgsCaller 异常以进入 Java 入口。

3. 为什么是 Socket 而不是 Binder?

这是一个经典考点。Zygote 使用 LocalSocket 监听请求而非 Binder,主要是为了规避 Fork 机制与多线程锁冲突 导致的死锁风险。在 fork 瞬间,子进程只会拷贝发起调用的线程,其他线程持有的锁将永远无法在子进程中释放。


4. 子进程的“觉醒”:ActivityThread.main()

fork 成功后,子进程会执行 ActivityThread.main() 方法,这标志着应用主线程正式开始工作:

  1. **Looper.prepareMainLooper()**:初始化主线程消息循环。
  2. attach:跨进程向 AMS 报告:“我启动好了(attachApplication)”。
  3. BIND_APPLICATION:AMS 发回应用配置信息,App 开始创建 Application 实例并调用 onCreate
  4. **Looper.loop()**:主线程进入死循环,开始处理 AMS 发来的生命周期指令(如 LAUNCH_ACTIVITY)。

5. 总结

进程创建是一个“从 C++ 到 Java”的过程,也是“从系统服务到应用代码”的过程。掌握了从 startProcessLockedattachApplication 的闭环,就掌握了 Android 进程管理的精髓。

Android Framework 专项 - WMS 学习路线指南

WindowManagerService (WMS) 是 Android 系统中负责窗口管理的核心服务。与 AMS 相比,WMS 与图形显示、输入系统及 View 系统的交互更为紧密。设计一套科学的 WMS 学习路线,建议遵循“从基础支撑到核心模型,再到显示原理”的原则。


第一阶段:支撑系统(底层依赖知识)

在深入 WMS 源码前,必须掌握 WMS 运行的基础设施。

模块 关键考点 学习目的
SurfaceFlinger 图形缓冲区、Layer、合成原理 理解 WMS 最终的渲染产物是如何被合成并显示的。
Input 系统 IMS、事件分发、InputChannel 理解 WMS 如何协助将点击事件派发到正确的窗口。
View 系统 ViewRootImpl、DecorView、Measure/Layout 理解应用端是如何通过 View 系统与 WMS 建立联系的。

第二阶段:核心模型(窗口的骨架)

WMS 服务端通过一组对象来维护窗口的层级、属性和状态。

核心类 职责描述 对应现实模型
WindowToken 标识一组窗口(如 Activity 下的所有 Window),用于权限和组织。 分组标签
WindowState 服务端对单个窗口的建模,存储大小、位置、可见性等信息。 窗口本体
DisplayContent 对应物理或虚拟屏幕,管理该屏幕下的所有窗口。 整个屏幕
Session 应用进程与 WMS 之间的 Binder 通道,每个进程一个。 通信信道

第三阶段:核心流程(窗口的诞生与消亡)

通过追踪一个 Activity 窗口从无到有的过程,理清 WMS 的运行逻辑。

学习步骤 核心关键点 关注重点
1. 窗口添加 (Add) WindowManagerGlobal -> WMS.addWindow 权限校验、WindowState 创建、Z-Order 分配。
2. 布局计算 (Relayout) WMS.relayoutWindow 窗口框架计算(Frame)、显示区域(Insets)的处理。
3. Surface 分配 WindowSurfaceController 理解 Surface 如何从 WMS 传递到应用进程。
4. 窗口移除 (Remove) removeWindow 状态同步、资源清理、窗口退出动画。

第四阶段:进阶专题(高级显示控制)

了解现代 Android 在复杂显示场景下的处理机制。

进阶专题 核心内容 学习意义
层级管理 (Z-Order) BaseLayer、SubLayer 计算规则。 理解窗口遮挡关系与叠加顺序。
窗口动画 WindowAnimationSpec、Remote Animation。 掌握 App 切换动画及系统动画的底层实现。
多窗口与分屏 TaskStack 组织、多任务焦点管理。 适配大屏、折叠屏等现代设备。
输入法窗口 (IME) IME 窗口的特殊层级与生命周期。 解决输入法遮挡及交互的疑难杂症。

💡 学习建议:

  1. 结合 Winscope 工具:利用 Android 提供的 Winscope 录制并查看窗口层级和 Surface 状态,将抽象代码可视化。
  2. 理解 Insets 机制:现代 Android 窗口管理很大一部分精力在于处理状态栏、导航栏、挖孔屏等带来的 WindowInsets
  3. 分层阅读:WMS 源码逻辑分散在 services 的核心包中,建议从 WindowManagerService.java 入手,先理清 addWindow 这一条主线。

WMS 专项 - 窗口添加流程解析 (AddWindow)

当应用端调用 WindowManager.addView 时,窗口的添加流程正式开启。这是一个跨越应用进程与 WMS 服务端的重要 IPC 过程。

1. 应用端:ViewRootImpl 的建立

WindowManagerGlobal 中,每添加一个窗口都会创建一个对应的 ViewRootImpl。它负责:

  • 触发第一次 requestLayout
  • 通过 mWindowSession.addToDisplay 向 WMS 发起跨进程调用。

2. 服务端:WMS.addWindow 核心逻辑

关键步骤 内部行为 目的
1. 权限与令牌校验 检查 WindowToken 是否合法。 确保如子窗口、Activity 窗口拥有正确的宿主权限。
2. 创建 WindowState 在 WMS 内部为该窗口建立“档案”。 存储窗口的所有几何属性、标志位及父子关系。
3. Z-Order 计算 根据 WindowType 分配显示层级。 决定窗口在垂直方向上谁盖住谁。
4. 关联 Session 将窗口与发起进程的 Session 绑定。 便于后续的 IPC 通信与异常清理。

3. 核心对象关系图

App 进程 (ViewRootImpl) <— IWindowSession (Binder) —> SystemServer (WMS)

  • WMS 持有 WindowToken (管理组)
  • WindowToken 包含多个 WindowState (管理个体)