Appearance
06 AMS 与 ATMS:四大组件的总调度台
本页导读:ActivityManagerService(AMS)曾是 Android 最著名的「上帝类」,Android 10 把 Activity/任务栈的部分切出去成了 ActivityTaskManagerService(ATMS),两者至今共用一把大锁。本页讲清:拆分边界、一次
startActivity的完整链路(含进程不在时如何经 zygote 孵化)、进程状态与 OOM 优先级、ANR 的判定与归因,以及 ActivityRecord/Task/TaskFragment 这棵窗口容器树。基线 Android 16(API 36)。
一、一分为二:AMS 管进程,ATMS 管活动
Android 10 的拆分是「按关注点」而非「按进程」——两者仍运行在 system_server 同一进程,互持引用、共用 ActivityManagerService.mLock(代码位于 frameworks/base/services/core/java/com/android/server/am/ 与 .../wm/):
| 服务 | 管什么 | 关键入口 |
|---|---|---|
| AMS | 进程生命周期、OOM adj、广播、服务、ContentProvider、ANR 记账 | am/ActivityManagerService.java |
| ATMS | Activity 启动、任务栈(Task/TaskFragment)、返回栈、最近任务 | wm/ActivityTaskManagerService.java |
| 共同地基 | ProcessList、进程状态机、Attach 链路、AppDomain 数据 | am/ProcessList.java |
读代码的实用分界线:问「进程在不在、能不能活」找 AMS;问「Activity 起在哪、栈怎么排」找 ATMS。
二、一次 startActivity 的完整链路
text
Activity.startActivity()
→ Instrumentation.execStartActivity # 应用侧
→ ActivityTaskManagerService.startActivity # Binder 跨进 system_server
→ ActivityStarter(wm/ActivityStarter.java) # 权限/队列/分屏拦截,最终 execute
→ ActivityStartController → 任务栈匹配 # Task 归属、launchMode、intent flags
→ ActivityRecord 生成,加入 Task,置 RESUMED 候选
→ 目标进程不在?→ startProcess(见第三节)
→ ActivityTaskSupervisor 下发 ClientTransaction
(LaunchActivityItem/ResumeActivityItem…) # Binder 回到应用
→ ActivityThread.handleLaunchActivity # 应用侧反射实例化、onCreate/onResume
→ 首帧 relayout/finish 走 WMS(第 07 页)链路里两个系统(ATMS 的 wm 包与 AMS 的 am 包)通过 ActivityTaskSupervisor/ClientLifecycleManager 合并下发小事务(ClientTransaction 里可以打包 launch+resume),减少 Binder 往返——这是 Android 10 拆分后「分家不分心」的典型设计。
三个常被追问的点:
- launchMode 不是玄学:standard/singleTop/singleTask/singleInstance 的差别全部落在
ActivityStarter的复用决策与Task归属上,Intent的 FLAG_ACTIVITY_* 同场叠加; - 后台启动限制:Android 10 起后台拉起 Activity 默认被拦截(白名单例外:有可见窗口、系统授权等),日志关键字
Background activity start; - PendingIntent 是把这条链路的「授权」提前封装——发出方以创建者身份执行,权限语义详见官方 PendingIntent 文档。
三、进程不在怎么办:attach 协议
java
// frameworks/base/services/core/java/com/android/server/am/ProcessList.java(示意骨架)
static Process.ProcessStart startProcessLocked(...) {
// 组装: 进程名、uid/gid、seclabel、targetSdk、mountUnion...
return mZygoteProcess.start(...); // 走到第 02 页的 socket 孵化
}新进程活着回来后,故事才走了一半:
text
ApplicationThread.attachApplication(AMS 反向 Binder 调用)
→ AMS.attachApplication → attachApplicationLocked
→ bindApplication:下发 ApplicationInfo/配置/Provider 清单
→ 应用侧 makeApplication → ContentProvider 安装 → 回调 AMS 就绪
→ ATMS 继续 attach 完成后排队的 ClientTransaction(起 Activity/Service)注意「孵化」与「attach」是两个时刻:zygote fork 成功但 attach 前死亡(native 崩溃、SELinux 拒绝)表现为 Process ... has died 且无 Java 栈。
四、IIntentReceiver 与广播触发的进程启动
隐式广播/显式广播找不到存活进程时,BroadcastQueue 会对「需要运行的接收者」发起进程启动:同样是上述 attach 协议,只是完成后排队的变成 ReceiverItem。Android 12 重写了广播队列(BroadcastQueueModern),核心思想是:每条广播带自己的截止与超时、并发受控、按 uid 记账配额。
IIntentReceiver(frameworks/base/core/java/android/content/IIntentReceiver.aidl)是应用注册广播时交给系统的回调 Binder,AMS 经performReceive把ReceiverItem投到主线程队列(第 05 页);- 动态接收者(
registerReceiver)注册在BroadcastQueue的 app-side 记录里,进程死亡即自动消失——这是「注册要配对 unregister」的根因; - 前台广播超时 10s、后台 60s(AOSP 参考值,
BroadcastQueue常量),超时同样汇入 ANR 账本(见第六节)。
五、进程状态与优先级:活着几等
OOM 调整器(OomAdjuster)给每个进程定档,从高到低(示意,常量以 AOSP ProcessList.java 为准):
| 状态档 | 典型代表 | 后果 |
|---|---|---|
| persistent | system_server、persistent 系统应用 | 永不杀,开机即活 |
| foreground/top | 前台 Activity、正在执行的交互 | 基本不杀 |
| foreground service | 合规 FGS(前台服务,Android 14 起类型强约束) | 低概率被杀 |
| perceptible | 用户可感知(如正在投屏、通话关联进程) | 中低概率 |
| bound/visible | 被前台绑定的服务进程、可见非前台 | 中高概率 |
| cached | 无组件在跑的缓存进程 | 第一个被杀,freezer 可冻结 |
状态机不是标签而是账本:adj 值、oom adj、进程组、freezer 状态全部由 OomAdjuster 统一计算并下发内核,dumpsys activity process <pkg> 的 curAdj/rawAdj/adjSeq 三列就是账本余额。
三个实践要点:
- 状态决定 oom_score_adj,lmkd 按分数收割(第 00 页);
- cached 进程在 Android 11+ 默认进 cgroup freezer(内核 cgroup freezer 控制器),冻结≠杀死,Binder 调用会先唤醒对方——「调用卡住几秒」的经典原因;
- 绑定服务的连接强度(
BIND_AUTO_CREATE/BIND_WAIVE_PRIORITY等 flag)直接影响对方进程档次,「绑个服务把自己变成 perceptible」是合法保命手段,但滥用会被计账(第 11 页省电策略会对账)。
六、ANR:判定、归因与报告
ANR 不是「卡死」,而是「关键路径超过阈值」:
| 类型 | 典型阈值(AOSP 参考,常量以源码为准) | 判定者 |
|---|---|---|
| 输入事件 | 5s(按键分发 Android 12+ 放宽到 10s 量级) | InputDispatcher 超时回调(第 09 页) |
| 广播 | 前台 10s / 后台 60s | BroadcastQueueModern |
| Service 启动/绑定 | 前台 20s / 后台 200s | ActiveServices(ActiveServices.java) |
| ContentProvider 发布 | 10s 量级 | ContentProviderHelper |
判定在 system_server(AppErrors/AnrHelper,services/core/java/com/android/server/am/AnrHelper.java),归因三件套:主线程栈 + CPU 占用 + 消息队列里堆着什么。ANR 确认后的固定动作序列:采集目标进程与 system_server 线程栈 → 落 /data/anr/ 与 dropbox → 按类型决定是否弹对话框 → 记录到电池/稳定性统计(第 11 页)。Android 12+ 的 ANR 报告是结构化 artifact(anr_* 文件与 trace),SystemUI 弹「无响应」对话框;ANR 对话框归属 SystemUI(Android 11+ framework 只发意图,UI 在 SystemUI 侧)。
实战:dumpsys activity 的 errors 段与 /data/anr/ 是取报告第一站;Subject: 行、Rss/CPU usage 段、主线程 held mutator lock 行,三眼看完基本定性。
七、ActivityRecord、Task、TaskFragment:容器树
text
RootWindowContainer
└ DisplayContent
└ TaskDisplayArea(Android 11+,分屏/自由窗的容器位)
└ Task(栈;可嵌套子 Task)
└ TaskFragment(Android 12+,多窗口配对/嵌入式成对容器)
└ ActivityRecord(一个 Activity 实例的服务端化身)ActivityRecord持有Intent、进程引用、状态机(INITIALIZING→RESUMED→PAUSED/STOPPED/DESTROYED);Task的affinity与taskAffinity决定跨应用复用;最近任务列表就是 Task 的投影;- 多窗口(分屏/大屏多任务)从 Android 12 的
TaskFragment与ActivityEmbedding(应用内SplitPair规则)继续演进,Android 15/16 强化大屏自适应——但启动决策仍在ActivityStarter/ActivityStartController; dumpsys activity activities是这棵树的可读化输出,排查「回不去、起错栈、最近任务少了」先看它。
顺带区分两个 dump 子命令:activities 看容器树与回退栈,procs 看进程表与 adj——「起错栈」查前者,「被杀/不活」查后者。
常见启动异常速查:
- 起不来:
ActivityStarter拦截日志(权限、后台限制、锁屏遮罩); - 起错栈/重复起:taskAffinity、launchMode、
allowTaskReparenting三件套逐一对; - 起来就退:目标
onCreate抛异常,先看 crash 再看栈; - 白屏一下才进去:启动窗口/SplashScreen 阶段处理(系统提供的 starting window 机制,表现随版本有差异)。
八、Service 与 ContentProvider:同一把锁下的另两件事
Service(ActiveServices.java):
startService链:ATMS/应用 → AMS → ActiveServices 建ServiceRecord→ 必要时启进程(第三节链路)→ 主线程scheduleServiceArgs排队执行;返回 START_STICKY/START_NOT_REDELIVER 等决定被杀后是否重建;bindService链额外维护连接计数与进程依赖边(第五节的 adj 传播就来自这些边);startForeground是 FGS 的入场券:Android 14(API 34)起必须声明类型并满足可见性要求,否则当场崩溃;超时阈值(前台 20s/后台 200s)由 ActiveServices 计时;ServiceRecord上能看到「最近一次 start 时间、连接列表、ANR 计数」,dumpsys activity services子命令(以版本为准)直接可读;- 「服务不回调」类 bug 先看它是否已被停止(START_STICKY 重启语义)再看进程是否已死——两段排查不要混。
ContentProvider(ContentProviderHelper.java):
- 发布时机:
bindApplication下发列表后、Application.onCreate之前安装(ContentResolver.call/query才能立刻可用);这也是「Application 未建 Provider 已可用」的原理; - 获取链:
acquireProvider→ 必要时启进程 → 超时计入 ANR 账本;跨进程返回的 Cursor 是 Binder + fd 双通道(第 04 页); - FileProvider 是把文件权限包装成 content URI 的标准做法,避免
file://被 StrictMode 拦截(API 24+)。
九、进程死亡:崩溃处理与重启策略
Java 崩溃由 ApplicationCrashHandler(AM 包内)接管:抓栈→分类(FATAL / FATAL EXCEPTION)→ dropbox 落盘 → 视情况杀进程组;persistent 进程崩溃会触发系统重启路径。
- 普通应用崩溃:只杀自己进程组(同一 appId 的多进程一起),其它应用无感;
ApplicationExitInfo记录死因,重启策略由组件语义决定(Service 按 onStartCommand 返回值,Activity 按栈状态);- 调试:
am kill <package>杀指定包缓存进程,am kill-all清全机缓存(am 子命令以 AOSP 实现为准);崩溃回放用dumpsys dropbox --print; - 「被系统杀还是自己崩」的判断:dropbox 有没有对应
crash条目 +lmd事件(logcat -b events的lmkd/am_kill事件)交叉比对。
十、版本注记
- Android 8~9(API 26~28):后台启动限制酝酿(隐式广播限制先行);进程缓存开始 freezer 实验。
- Android 10(API 29):AMS/ATMS 正式拆分;后台拉起 Activity 默认禁止。
- Android 11(API 30):cached app cgroup freezer 正式引入;TaskDisplayArea 容器化。
- Android 12(API 31):广播队列重写 BroadcastQueueModern;TaskFragment 登场;ANR 报告结构化。
- Android 14(API 34):FGS 类型强约束与可见性收紧;预测式返回影响回退栈体验。
- Android 15~16(API 35~36):大屏方向(大屏多窗、
ActivityEmbedding引导)持续推进;ANR/进程记账继续细化——主干骨架无破坏性变更。
本页小结
本页小结:ATMS 决定「起在哪、给谁看」,AMS 决定「谁有资格活、死了算谁的」;两者之间的 attach 协议是 Android 进程世界最重要的握手。ANR 记住一张表加一条链:四类阈值各管各的,归因永远回到「主线程 + 消息队列」。容器树则是窗口世界(第 07 页)的骨架,两棵树一一对应。
最后串一次页:孵化用第 02 页的 zygote,握手用第 04 页的 Binder,排队用第 05 页的队列,展示用第 07 页的窗口,档案查第 08 页的 PMS——四大组件只是这五件事的不同编排。
参考
- 进程与生命周期官方说明:developer.android.com/guide/components/fundamentals
- ActivityManagerService 源码:cs.android.com/android/platform/frameworks/base/+/main/services/core/java/com/android/server/am/ActivityManagerService.java
- ActivityTaskManagerService 源码:cs.android.com/android/platform/frameworks/base/+/main/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
- ProcessList 源码:cs.android.com/android/platform/frameworks/base/+/main/services/core/java/com/android/server/am/ProcessList.java
- 进程生命周期与进程优先级:developer.android.com/guide/topics/lifecycle(进程生命周期章)
- ANR 与调试官方指引:developer.android.com/topic/performance/anr(ANR 报告解读章)