
AMS 启动 Activity
在 Android 系统中,用户点击应用图标或调用startActivity()时,看似简单的 "界面跳转",实则是 AMS(运行于 SystemServer 进程)与应用进程、Zygote 进程、WMS(窗口管理服务)等多角色协同的复杂过程。
整个流程以 "跨进程通信(Binder)" 为纽带,围绕 "组件校验→栈管理→进程准备→Activity 创建→窗口显示" 展开。
本文将按时序拆解每个关键环节,还原 Activity 从 "启动请求" 到 "用户可见" 的全链路。
启动流程的核心角色与数据结构
在深入流程前,需明确参与方及关键数据结构(部分已在前文提及,此处聚焦启动场景):
| 角色 / 结构 | 归属进程 | 核心作用 |
|---|---|---|
| AMS(ActivityManagerService) | SystemServer 进程 | 统筹启动流程:校验权限、管理任务栈、调度进程、通知应用创建 Activity |
| ActivityManager | 应用进程 | AMS 的客户端代理,应用通过它发起startActivity()请求(封装 Binder 调用) |
| ApplicationThread | 应用进程 | 应用进程的 Binder 服务端,接收 AMS 的指令(如 "创建 Activity""触发生命周期") |
| ActivityThread | 应用进程 | 应用的主线程调度器,负责执行 Activity 生命周期、创建 Activity 实例 |
| ActivityRecord | SystemServer 进程 | 单 Activity 的状态载体:记录组件信息(如ComponentName)、生命周期状态、所属任务栈 |
| TaskRecord | SystemServer 进程 | 任务栈载体:管理同一任务下的所有 ActivityRecord,保证 "返回栈" 逻辑 |
| ActivityStackSupervisor | SystemServer 进程 | 任务栈的顶层管理者:决定 Activity 入哪个栈、是否创建新栈、调整栈内 Activity 顺序 |
| Zygote 进程 | 独立进程 | 孵化器:接收 AMS 请求,创建新的应用进程(若目标进程未启动) |
| WMS(WindowManagerService) | SystemServer 进程 | 窗口管理者:在 Activity resume 阶段,接收 AMS 指令,添加 Activity 窗口并显示 |
从startActivity到 AMS 调用
应用进程(如当前运行的 Activity 所在进程)发起启动请求时,并非直接操作 Activity,而是通过 "代理→Binder 通信" 将请求传递给 AMS。
具体步骤如下:
1. 应用层调用:startActivity()的上层封装
无论是用户点击按钮调用startActivity(new Intent(this, TargetActivity.class)),还是系统发起的启动(如启动桌面 Launcher),最终都会进入ContextImpl的实现(应用的Context实际是ContextImpl实例),核心调用链为:
java
// 应用层调用
Activity.startActivity(Intent);
→ ContextImpl.startActivity(Intent);
→ ActivityManager.startActivity(Intent) // 应用进程的AMS代理(ActivityManager)
此处的ActivityManager是应用进程的 "客户端代理",它不直接处理逻辑,而是将请求通过 Binder 发送给 SystemServer 进程的 AMS。
2. Instrumentation 拦截:启动前的应用层校验
在ContextImpl.startActivity()中,会先经过Instrumentation(应用的 "工具类",负责监控组件生命周期)的拦截,执行基础校验:
-
检查
Intent是否为空、是否设置了目标组件(ComponentName); -
若为 "隐式 Intent",则通过
PackageManager(PMS 的客户端代理)查询匹配的 Activity(避免无匹配组件导致启动失败)。
3. Binder 跨进程:请求传递至 AMS
Instrumentation校验通过后,会调用ActivityManager.getService().startActivityAsUser(...)------ 这里的getService()获取的是 AMS 的 Binder 代理(IActivityManager),通过 Binder 驱动,将启动请求从应用进程 "跨进程传递" 到 SystemServer 进程的 AMS。
AMS 校验、栈管理与进程判断
AMS 收到启动请求后,需完成 "合法性校验→任务栈调度→目标进程状态判断" 三大核心操作,这是决定启动能否继续的关键环节。
1. 合法性校验:权限与组件双重检查
AMS 首先执行严格校验,避免非法启动(若校验失败,直接抛出异常,如ActivityNotFoundException):
-
组件校验 :通过 PMS 查询目标 Activity 是否在
AndroidManifest.xml中注册(PMS 存储了所有应用的组件信息,AMS 与 PMS 同属 SystemServer 进程,可直接内存调用,无需 IPC); -
权限校验 :检查发起进程是否拥有启动目标 Activity 的权限(如目标 Activity 声明了
android:permission,则需发起进程在 Manifest 中声明对应权限); -
Intent 校验 :检查
Intent的flags是否合法(如FLAG_ACTIVITY_NEW_TASK是否符合栈管理规则)、目标 Activity 是否为 "导出状态"(android:exported="true",非本应用组件需导出才能被启动)。
2. 任务栈管理:创建 ActivityRecord 与调度 TaskRecord
校验通过后,AMS 会通过ActivityStackSupervisor(栈管理者)完成 "Activity 入栈" 逻辑,核心是创建ActivityRecord并分配到对应的TaskRecord:
-
创建 ActivityRecord :AMS 为目标 Activity 创建
ActivityRecord实例,记录关键信息(如发起进程 ID、目标组件名、生命周期状态初始化为INITIALIZING); -
确定目标 TaskRecord :
ActivityStackSupervisor根据Intent的flags(如FLAG_ACTIVITY_NEW_TASK)和 "任务栈亲和性"(android:taskAffinity),决定 Activity 进入哪个栈:
-
若
Intent带FLAG_ACTIVITY_NEW_TASK且无匹配亲和性的栈,则创建新的TaskRecord; -
若有匹配的现有栈(如同应用的默认栈),则将
ActivityRecord加入该栈的栈顶;
- 调整栈内顺序 :若存在 "栈内复用" 场景(如
FLAG_ACTIVITY_SINGLE_TOP),则将目标ActivityRecord移至栈顶,同时销毁其上方的ActivityRecord(触发对应 Activity 的onDestroy())。
3. 进程判断:目标进程是否已启动
AMS 通过ActivityRecord关联的 "目标进程包名",查询系统中的ProcessRecord列表(记录所有进程状态),判断目标进程(即目标 Activity 所在的应用进程)是否已启动:
-
情况 1:目标进程已启动:直接进入 "阶段 3",通知应用进程创建 Activity;
-
情况 2:目标进程未启动:先触发 "进程创建流程",再进入后续步骤(这是冷启动与热启动的核心区别)。
AMS 请求 Zygote 创建进程
若目标进程未启动(如首次点击应用图标),AMS 需先请求 Zygote 创建新进程,流程如下:
-
AMS 发起进程创建请求 :AMS 调用
Process.start(),封装进程创建参数(如目标应用包名、进程名、uid/gid,这些信息从 PMS 获取),通过 Socket 通信(Zygote 监听特定 Socket 端口)将请求发送给 Zygote 进程; -
Zygote 创建进程 :Zygote 收到请求后,通过
fork()系统调用复制自身进程(利用 Linux 写时复制机制,复用预加载的框架类和资源,加速进程创建),生成新的应用进程; -
初始化应用进程 :新进程启动后,会执行
ActivityThread.main()方法(应用进程的入口):
-
创建
ActivityThread实例(应用主线程管理器); -
初始化
Looper(为主线程开启消息循环,处理 UI 和生命周期消息); -
创建
ApplicationThread实例(应用的 Binder 服务端,用于接收 AMS 指令),并通过ActivityManager.getService().attachApplication(mAppThread)将其注册到 AMS;
- AMS 绑定进程与 ActivityRecord :AMS 收到
attachApplication()请求后,将新进程的ProcessRecord与目标 Activity 的ActivityRecord关联,标记 "进程已就绪",进入下一步。
AMS 通过 Binder 触发 Activity 创建
无论目标进程是已启动还是新创建,AMS 最终都会通过ApplicationThread(应用的 Binder 服务端)向应用进程发送 "创建 Activity" 的指令,流程如下:
1. AMS 发起创建指令:scheduleLaunchActivity()
AMS 调用ApplicationThread.scheduleLaunchActivity(ActivityClientRecord)------ 此处的ActivityClientRecord是ActivityRecord的 "客户端副本",包含创建 Activity 所需的所有信息(如ActivityRecord引用、Intent、组件名),通过 Binder 传递到应用进程。
2. 应用进程接收指令:从 Binder 线程到主线程
应用进程的 Binder 线程池(负责接收 AMS 的 Binder 请求)收到scheduleLaunchActivity()后,会将任务封装为Message,通过Handler发送到应用主线程(ActivityThread的mH Handler)------ 因为 Android 要求 UI 操作和生命周期执行在主线程,Binder 线程不能直接操作。
3. 主线程处理:ActivityThread.handleLaunchActivity()
主线程的Looper处理Message时,调用ActivityThread.handleLaunchActivity(),这是应用进程创建 Activity 的核心入口,具体分两步:
-
创建 Activity 实例 :通过
Instrumentation.newActivity(ClassLoader, className, intent)创建目标 Activity 实例(ClassLoader加载 Activity 类,避免类加载冲突); -
初始化 Application(首次启动时) :若应用的
Application未创建,会先通过Instrumentation.callApplicationOnCreate(app)创建Application并执行onCreate()(整个应用生命周期仅执行一次)。
Activity 生命周期执行与窗口显示
Activity实例创建后,ActivityThread会按顺序触发其生命周期方法,同时与 WMS 协同完成窗口显示,这是 Activity 从 "内存对象" 变为 "用户可见界面" 的关键环节。
1. 触发早期生命周期:onCreate() → onStart() → onPause()(当前栈顶 Activity)
-
onCreate()执行 :ActivityThread调用Instrumentation.callActivityOnCreate(activity, bundle),触发Activity.onCreate(savedInstanceState)------ 此时 Activity 完成布局加载(setContentView()),但窗口尚未显示; -
onStart()执行 :紧接着调用callActivityOnStart(activity),触发onStart()------Activity 进入 "可见但不可交互" 状态; -
当前栈顶 Activity 暂停 :若启动新 Activity 前,已有 Activity 在栈顶(如从 A 启动 B),AMS 会先通知原 Activity 所在进程执行
onPause()(通过ApplicationThread.schedulePauseActivity()),确保 "先暂停旧界面,再启动新界面"(避免界面重叠)。
2. AMS 与 WMS 协同:为新 Activity 准备窗口
在新 Activity 执行onStart()后,AMS 会向 WMS 发送 "添加窗口" 的请求:
-
AMS 通知 WMS :AMS 调用
WMS.addWindow(),传递ActivityRecord关联的窗口信息(如窗口大小、类型、所属进程); -
WMS 创建窗口对象 :WMS 为 Activity 创建
WindowState实例(记录窗口状态),并分配窗口 Z 序(确保新 Activity 窗口在最上层); -
应用进程创建 Window :应用进程的
Activity通过PhoneWindow(Window的实现类)创建DecorView(窗口的根视图),并将setContentView()加载的布局添加到DecorView。
3. 触发onResume():Activity 进入 "可交互" 状态
-
AMS 发起 resume 指令 :当 WMS 窗口准备就绪,AMS 调用
ApplicationThread.scheduleResumeActivity(),通知应用进程触发onResume(); -
onResume()执行 :ActivityThread调用Instrumentation.callActivityOnResume(activity),触发Activity.onResume()------ 此时 Activity 的DecorView被添加到 WMS 的窗口体系中; -
WMS 显示窗口 :WMS 通过
SurfaceFlinger(图形渲染服务)将DecorView的内容渲染到屏幕,Activity 正式 "用户可见且可交互"。
总结
整个启动流程可概括为 "三进程协同、两重校验、一次窗口渲染"
-
三进程协同:应用进程(发起请求、创建 Activity)→ SystemServer 进程(AMS 统筹、WMS 管窗口)→ Zygote 进程(冷启动时创建应用进程);
-
两重校验 :应用层
Instrumentation基础校验 → AMS 层权限 + 组件 + Intent 合法性校验; -
一次窗口渲染 :从
onCreate()加载布局到 WMS+SurfaceFlinger 渲染,完成 "内存对象→屏幕显示" 的转化。
关键设计思路:
-
跨进程通信依赖 Binder :AMS 与应用进程的交互全靠
IActivityManager(AMS 代理)和ApplicationThread(应用 Binder 服务端),确保指令高效传递; -
任务栈管理保证用户体验 :通过
TaskRecord和ActivityStackSupervisor维护 "返回逻辑",让用户点击返回时能按启动顺序退出; -
多服务协同实现功能闭环:AMS 主导流程,PMS 提供组件信息,WMS 管理窗口,Zygote 负责进程创建,缺任一环节均无法完成启动。
