Skip to content

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
ATMSActivity 启动、任务栈(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 拆分后「分家不分心」的典型设计。

三个常被追问的点:

  1. launchMode 不是玄学:standard/singleTop/singleTask/singleInstance 的差别全部落在 ActivityStarter 的复用决策与 Task 归属上,Intent 的 FLAG_ACTIVITY_* 同场叠加;
  2. 后台启动限制:Android 10 起后台拉起 Activity 默认被拦截(白名单例外:有可见窗口、系统授权等),日志关键字 Background activity start;
  3. 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 为准):

状态档典型代表后果
persistentsystem_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 三列就是账本余额。

三个实践要点:

  1. 状态决定 oom_score_adj,lmkd 按分数收割(第 00 页);
  2. cached 进程在 Android 11+ 默认进 cgroup freezer(内核 cgroup freezer 控制器),冻结≠杀死,Binder 调用会先唤醒对方——「调用卡住几秒」的经典原因;
  3. 绑定服务的连接强度(BIND_AUTO_CREATE/BIND_WAIVE_PRIORITY 等 flag)直接影响对方进程档次,「绑个服务把自己变成 perceptible」是合法保命手段,但滥用会被计账(第 11 页省电策略会对账)。

六、ANR:判定、归因与报告 ​

ANR 不是「卡死」,而是「关键路径超过阈值」:

类型典型阈值(AOSP 参考,常量以源码为准)判定者
输入事件5s(按键分发 Android 12+ 放宽到 10s 量级)InputDispatcher 超时回调(第 09 页)
广播前台 10s / 后台 60sBroadcastQueueModern
Service 启动/绑定前台 20s / 后台 200sActiveServices(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 报告解读章)

基于 Android 16 / API 36 · 内容为原创整理,转载请注明出处