如果把早期 Android Framework 看成一家刚起步的公司,AMS 很像那个什么都管的负责人:Activity 怎么启动、进程何时创建、Service 怎么运行、广播发给谁、Provider 是否存活,都由它统筹。
后来 Android 支持了多窗口、多屏、多用户、画中画、复杂动画和更严格的后台限制。AMS 没有消失,却不再独自维护所有状态。今天的 Android 16 中,AMS、ATMS、WMS 形成了一组分工明确的控制面。
这段历史经常被概括成“AMS 拆成了 AMS、ATMS、WMS”,但这个说法并不严谨:WMS 从早期 Android 就是独立服务,真正从 AMS 领域迁出的主要是 Activity 与 Task 管理。
本文沿着这条主线回答四个问题:早期 AMS 为什么要做成“大总管”;它为什么遇到瓶颈;Activity/Task 为什么最终形成 ATMS;Android 16 中 AMS、ATMS、WMS 到底怎样协作。
本文当前实现以 Android 16 产品 Framework 基线为准,Android 17 源码只用于观察趋势,不替代 Android 16 的函数与策略结论。
一张图看懂演进:拆的不是代码,而是状态所有权

图 1:WMS 始终独立存在;Android 的主线变化是 Activity/Task 从 AMS 领域迁出并形成 ATMS,AMS 则收敛为应用运行态与资源策略中枢。
早期架构可以简化为:
AMS:Activity + Task + Process + Service + Broadcast + Provider
↕
WMS:Window + Display + Surface
现代架构则变成:
ATMS:Activity / Task / Display 上的活动组织
↕
WMS:Window / Display / Surface / 输入窗口
↕ 可见性与进程投影
AMS:Process / Service / Broadcast / Provider / OOM / 后台策略
表面看是类和接口的迁移,真正变化的是“谁拥有最终解释权”:
- Activity 位于哪个 Task、哪个 Display,由 ATMS 决定;
- 窗口怎样布局、显示和提交 Surface,由 WMS 决定;
- 进程为何重要、是否可冻结、Service 和 Provider 是否存活,由 AMS 决定。
早期 AMS 为什么必须是“大总管”
Android 四大组件不是四套互不相关的机制。
启动 Activity 时,目标进程可能还不存在;绑定 Service 会改变服务进程的重要性;获取 Provider 会建立跨进程存活依赖;Broadcast 可能拉起前三类组件。早期设备单屏为主、任务模型简单,把这些状态放在 AMS 的同一套管理体系里,反而最容易保证一致性。
当时 AMS 领域大致包括:
| 子系统 | 主要职责 |
|---|---|
| Activity/Task | 启动、栈和任务、生命周期、前后台切换 |
| Process | fork、attach、LRU、OOM adj、死亡清理 |
| Service | start/bind、超时、前台服务 |
| Broadcast | 并行/有序广播、超时、进程拉起 |
| Provider | 发布、获取、引用计数、死亡处理 |
| User/Error | 多用户运行态、ANR、Crash 与权限协同 |
WMS 此时已经独立负责窗口。AMS 决定“哪个 Activity 应当运行”,WMS 决定“它的窗口怎样显示”。
这种设计的优势是直接:一个全局协调者可以在组件变化后立即更新进程优先级。它的缺点也埋在这里——Activity 历史与 Window 层级分别保存在两个强耦合系统中。
真正逼出 ATMS 的,不是 AMS 文件太长
如果只是代码量大,把类拆成几个 Helper 就够了。ATMS 出现的根本原因,是 Activity、Task、Window 和 Display 逐渐形成同一套拓扑。
从一块屏到多块屏
早期 Activity Stack 相对简单。后来 Android 陆续加入多 Stack、分屏、画中画、自由窗口、TaskFragment 和多 Display。到了 AAOS,一台车同时拥有中控、仪表、副驾和后排屏已经不是边缘情况。
Activity 位于哪个 Display、采用什么 windowing mode、是否可见,都会立即影响窗口层级、焦点、配置和动画。如果 AMS 维护一棵 Activity 树,WMS 再维护一棵 Window 树,系统就必须持续同步两份真相。
两类状态的节奏完全不同
窗口焦点、旋转、动画和 Transition 是高频界面状态;Service、Provider、进程 LRU 和 OOM adj 是应用运行态。让它们长期共享一个巨型状态机,会放大锁竞争,也让窗口功能的改动穿透到进程治理。
于是 Android 采用了一条渐进路线:
- 先用
ActivityStackSupervisor、ActivityStarter等对象从 AMS 主类提炼职责; - 再让 Activity、Task、Display 相关实现向
com.android.server.wm聚合; - 最终在 Android 10 形成
IActivityTaskManager与ActivityTaskManagerService; - 继续以统一的
WindowContainer体系承载 Display、Task、Activity 和 Window 之间的结构关系。
这是一种很典型的架构演进:先在单体内部建立边界,再移动状态所有权,最后才形成稳定服务接口。
Android 10 之后:AMS 为什么还保留 startActivity()
阅读源码时很容易产生疑问:Android 16 的 ActivityManagerService 中仍然能找到 startActivity(),是不是 Activity 其实还归 AMS?
看调用方向就清楚了:
// ActivityManagerService.java(省略参数)
public int startActivity(...) {
return mActivityTaskManager.startActivity(...);
}
这是兼容入口,不是权威状态仍留在 AMS 的证据。真正的启动流程进入 ATMS:
ActivityTaskManagerService.startActivityAsUser()
-> ActivityStartController.obtainStarter(...).execute()
-> ActivityStarter:解析、权限/BAL、Task 与 Display 选择
-> RootWindowContainer / Task:更新容器和可见性
判断一个功能属于谁,不能只看“哪个类还能收到入口调用”,而要看:核心状态存在哪里、谁能修改它、锁由谁持有、最终裁决发生在哪里。
Android 16 中,三大服务各自管什么
图 2:ATMS/WMS 拥有界面容器状态,AMS 拥有应用运行态;LMKD、cgroup/freezer 等位于策略执行层。
AMS:应用运行态与资源策略中枢
Android 16 的 AMS 继承 IActivityManager.Stub,主要子系统包括:
ProcessList:进程表、LRU、进程创建与退出记录;ProcessStateController、OomAdjusterImpl:根据组件和跨进程依赖计算 proc state、adj 与调度组;CachedAppOptimizer:缓存进程 compaction 与 freezer;ActiveServices:Service/FGS 生命周期、超时和后台准入;BroadcastController、BroadcastQueueImpl:广播解析与调度;ContentProviderHelper:Provider 获取、发布和引用;AppRestrictionController:应用后台限制聚合;AppStartInfoTracker、AppExitInfoTracker:启动与退出原因的结构化记录;UserController:用户运行态。
AMS 回答的是:进程为什么存在、因什么组件而重要、后台执行是否允许、何时应压缩或冻结、一次启动和退出为何发生。
ATMS:Activity 与 Task 的权威状态
ATMS 继承 IActivityTaskManager.Stub。源码对它的定义很直接:管理 Activity 及其容器,包括 Task 和 Display。
它的关键模块有:
ActivityStartController/ActivityStarter:启动入口与单次启动状态机;ActivityTaskSupervisor:跨 Task/Display 调度和应用 attach;RootWindowContainer:显示与任务容器树根;RecentTasks:最近任务;BackgroundActivityStartController:后台 Activity 启动裁决;LockTaskController:锁定任务模式;WindowProcessController:进程在 wm 领域的界面状态投影。
ATMS 回答的是:Activity 应进入哪个 Task、落在哪个 Display、谁可见、谁 resumed、生命周期下一步是什么。
WMS:窗口与显示系统
WMS 继承 IWindowManager.Stub,负责 Window session、WindowState、焦点、输入窗口、布局、Surface、DisplayContent、旋转和配置等。
它回答的是:窗口在哪里、层级如何、怎样布局和提交 Surface。它不负责判断一个 Service 是否应抬高进程优先级,也不管理 Broadcast 和 Provider。
ATMS 与 WMS 位于同一个 server.wm 领域并共享窗口管理全局锁,是因为 Activity/Task 与 Window/Display 必须保持同一棵容器拓扑;但它们仍保留不同的 Binder 契约和职责。
一次 Activity 启动,三大服务怎样接力

图 3:ATMS 主导任务与生命周期,AMS 提供进程并计算资源优先级,WMS 完成窗口呈现。
把调用链压缩到架构层,大致是:
App
-> IActivityTaskManager.startActivity
-> ATMS / ActivityStarter
-> 解析 Intent、检查权限和 BAL、选择 Task/Display
-> 更新 RootWindowContainer
-> 判断目标进程是否存在
├─ 存在:调度 Activity 生命周期
└─ 不存在:请求 AMS / ProcessList 创建进程
-> Zygote fork
-> AMS.attachApplication
-> ATMS attachApplication(WindowProcessController)
-> 应用 ActivityThread 执行 launch/resume
-> WMS 创建、布局窗口并参与 Transition
-> 可见性反馈给 AMS
-> ProcessStateController / OomAdjuster 更新优先级
这条链解释了为什么拆分后系统仍需要紧密协作:
- ATMS 拥有“界面应该是什么状态”的真相;
- AMS 拥有“运行这个界面需要什么进程和资源”的真相;
- WMS 拥有“这个状态如何成为屏幕上的窗口”的真相。
拆分没有消灭复杂度,而是阻止复杂度继续集中在一个状态机里。
为什么 Service、Broadcast、Provider 仍留在 AMS
它们的共同特点是:权威状态与进程依赖强相关,却不属于窗口容器树。
以 Service 为例:
ActivityManagerService.startService
-> ActiveServices.startServiceLocked
-> 后台/FGS 准入
-> bringUpServiceLocked
-> 必要时 ProcessList.startProcessLocked
-> realStartServiceLocked
-> 更新 OOM 依赖
以 Provider 为例:客户端获得 Provider 后,连接本身就可能提升 Provider 进程的重要性。ContentProviderHelper.getContentProviderImpl() 不只是“查一个地址”,还需要处理权限、用户、进程拉起、引用计数和死亡传播。
Broadcast 同样可能触发冷启动,并影响系统吞吐与公平性。Android 16 的现代广播队列以目标进程为重要调度维度,解决的是冷启动风暴、紧急广播延迟和应用间公平问题。
这些能力留在 AMS,不是历史遗留,而是遵循“组件运行态与进程资源放在同一领域”的设计。
拆分后最难的部分:同一进程有两种视图
AMS 中有 ProcessRecord,ATMS/WMS 中有 WindowProcessController。
前者关心 pid、UID、Service、Provider、LRU、proc state 和 adj;后者关心 Activity、窗口可见性、配置和界面调度。它们不是两份平级真相,而应当是“权威状态 + 跨域投影”。
例如 Activity 可见性在 wm 领域产生,再反馈给 AMS 参与 OOM 计算;Service 绑定关系在 am 领域产生,不应该复制进窗口容器树。
这也是定制 Framework 时最重要的评审问题:
这个字段的权威所有者是谁?其他模块拿到的是事件、快照,还是另一份可写状态?
如果这个问题答不清,最终通常会出现三类 Bug:
- 窗口已经不可见,进程仍被错误地当作可见进程;
- 两侧字段更新顺序不同,导致偶现 Task 或 OOM 状态错乱;
- AMS lock 与 WindowManagerGlobalLock 交叉获取,形成 system_server 死锁。
对 AAOS 来说,这套架构不是“手机遗产”
AAOS 反而把拆分的价值放大了。
第一,多 Display 是默认场景。中控、仪表、副驾和后排屏要求 ATMS/WMS 明确管理 displayId、Task 归属、焦点和可见性,不能让进程管理代码凭经验猜测。
第二,多用户可能同时可见。驾驶员、乘员、访客和可见后台用户会共同影响组件启动与 Display 选择。“当前用户 + 默认屏”的隐含假设在车机中很危险。
第三,长生命周期业务容易诱发永久保活。车辆信号、媒体、电源和系统 UI 确实重要,但正确做法是把重要性映射为受约束、可撤销、可解释的 Service/FGS、绑定关系或系统身份,而不是直接写死 oom_score_adj。
第四,平台能力与产品配置必须分开。Android 16 支持缓存进程 freezer,不代表每条产品分支默认开启。当前分析的产品基线就在 CachedAppOptimizer 中带有关闭 freezer 的产品补丁。机制、AOSP 策略和产品默认值是三个层次。
从这次演进能学到什么
AMS 的变化提供了四条很通用的架构经验。
第一,按状态所有权拆,而不是按文件大小拆。
Activity 与 Task 迁入 ATMS,是因为它们与 Display/Window 形成统一容器拓扑;Service 留在 AMS,是因为它与进程依赖和后台策略形成闭环。
第二,兼容入口不等于权威状态。
AMS 中仍有转发式 startActivity()。阅读大型系统时,应追踪最终裁决和数据归属,而不是看到方法名就停止。
第三,服务拆分不等于进程隔离。
AMS、ATMS、WMS 都在 system_server。逻辑边界能改善架构,却不会自动消除锁、重入和慢调用风险。
第四,投影必须单向且可解释。
ProcessRecord 与 WindowProcessController 可以分别服务两个领域,但每类字段都应有明确权威来源。两份都可写的“缓存”迟早会成为两份真相。
结语
从早期 Android 到 Android 16,AMS 的演进并不是一个“大服务被越拆越小”的故事。
它更像一次持续多年的状态重构:Activity/Task 的权威状态进入 ATMS,Window/Display 继续由 WMS 负责,进程和非界面组件运行态留在 AMS;三者通过内部接口和受控投影,共同完成一次应用启动、呈现和资源治理。
所以今天再读 AMS,最有效的方法不是从一个 Binder 方法一路追到底,而是同时追四条线:
- 状态由谁拥有;
- 策略由谁裁决;
- 机制由谁执行;
- 结果由谁记录。
当这四条线对齐时,AMS、ATMS、WMS 就不再是三个容易混淆的缩写,而是现代 Android 应用运行控制面的三块清晰拼图。
参考源码
services/core/java/com/android/server/am/ActivityManagerService.javaservices/core/java/com/android/server/am/ProcessList.javaservices/core/java/com/android/server/am/ProcessStateController.javaservices/core/java/com/android/server/am/OomAdjusterImpl.javaservices/core/java/com/android/server/am/ActiveServices.javaservices/core/java/com/android/server/am/BroadcastQueueImpl.javaservices/core/java/com/android/server/am/ContentProviderHelper.javaservices/core/java/com/android/server/am/CachedAppOptimizer.javaservices/core/java/com/android/server/wm/ActivityTaskManagerService.javaservices/core/java/com/android/server/wm/ActivityStartController.javaservices/core/java/com/android/server/wm/ActivityStarter.javaservices/core/java/com/android/server/wm/ActivityTaskSupervisor.javaservices/core/java/com/android/server/wm/RootWindowContainer.javaservices/core/java/com/android/server/wm/WindowProcessController.javaservices/core/java/com/android/server/wm/WindowManagerService.javaservices/java/com/android/server/SystemServer.java