AMS (ActivityManagerService) 面试常见问题详解
一、AMS 整体架构
Q1:AMS 是什么?它在系统中扮演什么角色?
┌─────────────────────────────────────────────────────────────────┐
│ Android 系统架构中的 AMS │
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ App 进程 │ │
│ │ Activity / Service / BroadcastReceiver / ContentProvider │ │
│ │ │ │ │
│ │ IActivityManager (Binder Proxy) │ │
│ └────────────────────────┼──────────────────────────────────┘ │
│ │ Binder IPC │
│ ┌────────────────────────▼──────────────────────────────────┐ │
│ │ system_server 进程 │ │
│ │ │ │
│ │ ┌─────────────────────────────────────────────────────┐ │ │
│ │ │ ActivityManagerService (AMS) │ │ │
│ │ │ │ │ │
│ │ │ ┌───────────────┐ ┌────────────────────────────┐ │ │ │
│ │ │ │ Activity 管理 │ │ Service 管理 │ │ │ │
│ │ │ │ ActivityStack │ │ ActiveServices │ │ │ │
│ │ │ │ TaskRecord │ │ ServiceRecord │ │ │ │
│ │ │ │ ActivityRecord │ │ │ │ │ │
│ │ │ └───────────────┘ └────────────────────────────┘ │ │ │
│ │ │ ┌───────────────┐ ┌────────────────────────────┐ │ │ │
│ │ │ │ Broadcast 管理 │ │ 进程管理 │ │ │ │
│ │ │ │ BroadcastQueue │ │ ProcessRecord │ │ │ │
│ │ │ │ │ │ OomAdj / LMK │ │ │ │
│ │ │ └───────────────┘ └────────────────────────────┘ │ │ │
│ │ │ ┌───────────────┐ ┌────────────────────────────┐ │ │ │
│ │ │ │ Provider 管理 │ │ 内存管理 │ │ │ │
│ │ │ │ │ │ trimApplications │ │ │ │
│ │ │ └───────────────┘ └────────────────────────────┘ │ │ │
│ │ └─────────────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ ┌───────────────────┐ ┌───────────────────────────┐ │ │
│ │ │ WindowManagerService│ │ PackageManagerService │ │ │
│ │ └───────────────────┘ └───────────────────────────┘ │ │
│ └───────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
AMS 核心职责:
1. 四大组件的生命周期管理(启动/停止/绑定/销毁)
2. 进程管理(创建/回收/OomAdj 计算)
3. 任务栈管理(Task / Back Stack)
4. ANR 监控与处理
5. 内存管理与进程优先级调度
Q2:Android 10+ 架构变化 — ATMS 拆分
Android 10 之前: Android 10 之后:
┌──────────────────┐ ┌──────────────────┐
│ AMS │ │ AMS │
│ │ │ (进程/Service/ │
│ Activity管理 │ │ Broadcast/ │
│ Service管理 │ → │ Provider/内存) │
│ Broadcast管理 │ └────────┬─────────┘
│ Provider管理 │ │
│ 进程管理 │ ┌────────▼─────────┐
│ 内存管理 │ │ ATMS │
└──────────────────┘ │ ActivityTaskManager│
│ Service │
│ (Activity/Task/ │
│ Stack 管理) │
└──────────────────┘
原因:AMS 代码过于庞大(3万+行),拆分为:
- ATMS:专注 Activity 和 Task 管理
- AMS:保留进程、Service、Broadcast、Provider 管理
二、Activity 启动流程(最高频考点)
Q3:详述 Activity 的启动流程
startActivity(intent)
│
▼
┌──────────────────────────────────────────────────────────────┐
│ App 进程 (Caller) │
│ │
│ Activity.startActivity() │
│ → Instrumentation.execStartActivity() │
│ → ActivityTaskManager.getService() │
│ .startActivity(...) │
│ │ │
│ │ Binder IPC (IActivityTaskManager) │
│ ▼ │
└──────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────┐
│ system_server 进程 │
│ │
│ ATMS.startActivity() │
│ │ │
│ ▼ │
│ ActivityStarter.execute() │
│ ├── 1. 权限检查 (checkPermission) │
│ ├── 2. 解析 Intent (resolveActivity via PMS) │
│ ├── 3. 创建 ActivityRecord │
│ ├── 4. 处理 LaunchMode / Flags │
│ │ ├── 复用已有 Task? │
│ │ ├── 创建新 Task? │
│ │ └── 清除栈顶?(FLAG_ACTIVITY_CLEAR_TOP) │
│ ├── 5. 找到目标 ActivityStack │
│ └── 6. 调用 resumeTopActivity() │
│ │ │
│ ▼ │
│ ActivityStackSupervisor.startSpecificActivity() │
│ │ │
│ ├── 目标进程是否存在? │
│ │ │ │
│ │ ├── 存在 → realStartActivityLocked() │
│ │ │ │ │
│ │ │ ▼ │
│ │ │ 通过 IApplicationThread (Binder) │
│ │ │ 调用 app.thread.scheduleTransaction(...) │
│ │ │ │
│ │ └── 不存在 → AMS.startProcessLocked() │
│ │ │ │
│ │ ▼ │
│ │ Process.start("android.app.ActivityThread") │
│ │ → Zygote fork 新进程 │
│ │ → 新进程 ActivityThread.main() │
│ │ → attach 到 AMS │
│ │ → AMS 回调 realStartActivityLocked() │
│ │ │
└────┼─────────────────────────────────────────────────────────┘
│
│ Binder IPC (IApplicationThread)
▼
┌──────────────────────────────────────────────────────────────┐
│ App 进程 (Target) │
│ │
│ ApplicationThread.scheduleTransaction() │
│ → TransactionExecutor.execute() │
│ → 通过 Handler H 切到主线程 │
│ │
│ LaunchActivityItem.execute() │
│ → ActivityThread.handleLaunchActivity() │
│ → performLaunchActivity() │
│ ├── Instrumentation.newActivity() (反射创建Activity) │
│ ├── Activity.attach() (绑定Window/Context等) │
│ ├── Instrumentation.callActivityOnCreate() │
│ │ → Activity.onCreate() │
│ └── Activity.onStart() (如果需要) │
│ │
│ ResumeActivityItem.execute() │
│ → ActivityThread.handleResumeActivity() │
│ → Activity.onResume() │
│ → WindowManager.addView(decorView) │
│ → ViewRootImpl.setView() │
│ → requestLayout() → 触发绘制 │
│ │
└──────────────────────────────────────────────────────────────┘
Q4:生命周期是怎么回调的?(ClientTransaction 机制)
Android 9.0+ 引入 ClientTransaction/ClientLifecycleManager
┌──────────────────────────────────────────────────────┐
│ ClientTransaction 机制 │
│ │
│ AMS 侧: │
│ ┌────────────────────────────────────────────────┐ │
│ │ ClientTransaction transaction = new(...) │ │
│ │ │ │
│ │ // 添加 Callback (在目标生命周期前执行) │ │
│ │ transaction.addCallback(LaunchActivityItem) │ │
│ │ │ │
│ │ // 设置最终生命周期状态 │ │
│ │ transaction.setLifecycleStateRequest( │ │
│ │ ResumeActivityItem) │ │
│ │ │ │
│ │ // 通过 Binder 发送到 App 进程 │ │
│ │ clientLifecycleManager.scheduleTransaction() │ │
│ └────────────────────────────────────────────────┘ │
│ │
│ App 侧: │
│ ┌────────────────────────────────────────────────┐ │
│ │ TransactionExecutor.execute(transaction) │ │
│ │ │ │ │
│ │ ├── 1. executeCallbacks() │ │
│ │ │ → LaunchActivityItem.execute() │ │
│ │ │ → handleLaunchActivity() │ │
│ │ │ → onCreate() │ │
│ │ │ │ │
│ │ └── 2. executeLifecycleState() │ │
│ │ → 计算中间状态 (cycleToPath) │ │
│ │ → ON_CREATE → ON_START → ON_RESUME │ │
│ │ → 依次回调 onStart() → onResume() │ │
│ └────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────┘
生命周期状态枚举:
ON_CREATE(1) → ON_START(2) → ON_RESUME(3)
→ ON_PAUSE(4) → ON_STOP(5) → ON_DESTROY(6)
cycleToPath 会自动补齐中间状态:
当前 ON_CREATE(1), 目标 ON_RESUME(3)
→ 路径: ON_START(2), ON_RESUME(3)
→ 依次调用: onStart(), onResume()
三、进程管理(高频考点)
Q5:App 进程是怎么创建的?
AMS.startProcessLocked()
│
▼
Process.start("android.app.ActivityThread", ...)
│
▼
ZygoteProcess.start()
│
▼
通过 LocalSocket 连接 Zygote 进程
│
▼
┌──────────────────────────────────────────┐
│ Zygote 进程 │
│ │
│ ZygoteServer.runSelectLoop() │
│ → 接收到请求 │
│ → Zygote.forkAndSpecialize() │
│ → native fork() (Linux 系统调用) │
│ │
│ fork 的优势: │
│ ├── 写时复制 (COW) — 共享 Zygote 内存 │
│ ├── 预加载的类/资源直接可用 │
│ └── 启动速度快 │
└──────────────────────────────────────────┘
│
▼ (子进程)
┌──────────────────────────────────────────┐
│ 新 App 进程 │
│ │
│ ActivityThread.main() │
│ ├── Looper.prepareMainLooper() │
│ ├── new ActivityThread() │
│ ├── thread.attach(false) │
│ │ → AMS.attachApplicationLocked() │
│ │ ├── 创建 ProcessRecord │
│ │ ├── 绑定 ApplicationThread │
│ │ ├── 回调 bindApplication │
│ │ │ → handleBindApplication() │
│ │ │ → Application.onCreate()│
│ │ └── 启动 pending 的 Activity │
│ │ │
│ └── Looper.loop() ← 主线程消息循环 │
└──────────────────────────────────────────┘
Q6:进程优先级 & OomAdj 是什么?如何影响进程回收?
┌──────────────────────────────────────────────────────────────────┐
│ 进程优先级 (OomAdj) │
│ │
│ OomAdj 值越小 → 优先级越高 → 越不容易被杀 │
│ │
│ ┌──────────────┬─────────────┬──────────────────────────────┐ │
│ │ OomAdj 值 │ 级别 │ 说明 │ │
│ ├──────────────┼─────────────┼──────────────────────────────┤ │
│ │ -1000 │ NATIVE │ Native 进程 (init 等) │ │
│ │ -900 │ SYSTEM │ system_server │ │
│ │ -800 │ PERSISTENT │ 系统持久进程 (电话/蓝牙) │ │
│ │ 0 │ FOREGROUND │ 前台进程 (正在显示的 Activity) │ │
│ │ 100 │ VISIBLE │ 可见进程 (可见但非前台) │ │
│ │ 200 │ PERCEPTIBLE │ 可感知进程 (前台 Service) │ │
│ │ 300 │ BACKUP │ 备份进程 │ │
│ │ 600 │ HEAVY_WEIGHT│ 重量级进程 │ │
│ │ 700 │ SERVICE │ Service 进程 │ │
│ │ 800 │ HOME │ Launcher 进程 │ │
│ │ 900 │ PREVIOUS │ 上一个使用的进程 │ │
│ │ 999 │ CACHED │ 缓存进程 (空进程/后台Activity) │ │
│ └──────────────┴─────────────┴──────────────────────────────┘ │
│ │
│ LMK (Low Memory Killer) 按 OomAdj 从大到小回收 │
│ 内存不足时先杀 OomAdj=999 的缓存进程, 然后逐步杀更高优先级进程 │
│ │
│ AMS 动态计算 OomAdj: │
│ 有前台 Activity → FOREGROUND_APP_ADJ (0) │
│ Activity 退到后台 → CACHED_APP_MIN_ADJ (900) │
│ 启动前台 Service → PERCEPTIBLE_APP_ADJ (200) │
│ 绑定了前台进程 → 根据绑定关系提升 │
└──────────────────────────────────────────────────────────────────┘
Q7:怎么保活?AMS 如何影响进程保活?
┌────────────────────────────────────────────────────────────┐
│ 进程保活手段 & AMS 对策 │
├────────────────────────────────────────────────────────────┤
│ │
│ 手段1: 前台 Service (startForeground) │
│ → OomAdj 降到 PERCEPTIBLE(200) │
│ → AMS 合法认可, 最有效的保活方式 │
│ → Android 12+ 限制前台 Service 类型 │
│ │
│ 手段2: 1像素 Activity │
│ → 锁屏时启动透明1像素Activity, OomAdj降到0 │
│ → AMS 不区分大小, 只看是否有前台 Activity │
│ → Android 10+ 后台启动 Activity 限制 │
│ │
│ 手段3: 双进程守护 │
│ → 两个 Service 互相 bind, 一个死了另一个拉起 │
│ → AMS 识别到绑定关系, 但回收时可能同时杀死 │
│ → Android 8+ 大幅限制后台执行 │
│ │
│ 手段4: WorkManager / JobScheduler │
│ → 系统管理的延迟任务 │
│ → AMS 配合 JobSchedulerService │
│ → 不能保证实时性, 但任务最终会执行 │
│ │
│ 手段5: 账号同步 / 推送通道复用 │
│ → 接入厂商推送 (FCM / 华为 / 小米 Push) │
│ → 系统级保活 │
│ │
│ 趋势: Android 逐版本收紧后台限制 │
│ 8.0: 后台 Service 限制 │
│ 9.0: 后台传感器/WiFi扫描限制 │
│ 10.0: 后台启动 Activity 限制 │
│ 12.0: 前台 Service 类型限制 │
│ 13.0: 更严格的通知权限 │
└────────────────────────────────────────────────────────────┘
四、任务栈管理
Q8:Task、ActivityStack、ActivityRecord 的关系?
┌──────────────────────────────────────────────────────────────┐
│ Activity 管理数据结构 │
│ │
│ ActivityStackSupervisor (管理所有 Display 的 Stack) │
│ │ │
│ ├── ActivityDisplay 0 (主屏) │
│ │ ├── ActivityStack 0 (Home Stack — Launcher) │
│ │ │ └── TaskRecord (Launcher Task) │
│ │ │ └── ActivityRecord (Launcher Activity) │
│ │ │ │
│ │ ├── ActivityStack 1 (Fullscreen Stack) │
│ │ │ ├── TaskRecord 1 (App A 的 Task) │
│ │ │ │ ├── ActivityRecord (A_MainActivity) │
│ │ │ │ ├── ActivityRecord (A_DetailActivity) │
│ │ │ │ └── ActivityRecord (A_SettingsActivity) │
│ │ │ │ │
│ │ │ └── TaskRecord 2 (App B 的 Task) │
│ │ │ ├── ActivityRecord (B_MainActivity) │
│ │ │ └── ActivityRecord (B_EditActivity) │
│ │ │ │
│ │ └── ActivityStack 2 (Split Screen / PIP) │
│ │ │
│ └── ActivityDisplay 1 (外接屏幕) │
│ │
│ 关系说明: │
│ ActivityStackSupervisor → 1:N → ActivityDisplay │
│ ActivityDisplay → 1:N → ActivityStack │
│ ActivityStack → 1:N → TaskRecord │
│ TaskRecord → 1:N → ActivityRecord │
│ │
│ Android 12+ 重构: │
│ ActivityStack → Task (合并) │
│ TaskRecord → Task (合并) │
│ ActivityRecord 保留 │
└──────────────────────────────────────────────────────────────┘
Q9:LaunchMode 在 AMS 中是如何处理的?
ActivityStarter.startActivityUnchecked() 中处理:
┌────────────────────────────────────────────────────────────────┐
│ LaunchMode 处理逻辑 │
├────────────────────────────────────────────────────────────────┤
│ │
│ standard (默认): │
│ → 每次都创建新的 ActivityRecord │
│ → 放入调用者所在的 Task 栈顶 │
│ Task: [A] → startActivity(B) → [A, B] │
│ Task: [A, B] → startActivity(B) → [A, B, B] │
│ │
│ singleTop: │
│ → 如果目标 Activity 已在栈顶 → 不创建, 调用 onNewIntent() │
│ → 不在栈顶 → 和 standard 一样创建新实例 │
│ Task: [A, B] → start(B) → onNewIntent(B) → [A, B] │
│ Task: [A, B] → start(A) → [A, B, A] (不在栈顶,新建) │
│ │
│ singleTask: │
│ → 在整个系统中只有一个实例 │
│ → 不存在 → 新建 Task(如果 taskAffinity 不同) + ActivityRecord │
│ → 已存在 → 将该 Task 移到前台, 清除其上所有 Activity │
│ → 调用 onNewIntent() │
│ Task1: [A, B, C] (C是singleTask) │
│ start(C) → 清除 C 上面的 → Task1: [A, B, C] + onNewIntent │
│ │
│ singleInstance: │
│ → 独占一个 Task, 该 Task 中只能有这一个 Activity │
│ → 不存在 → 新建专属 Task + ActivityRecord │
│ → 已存在 → 调用 onNewIntent(), 将 Task 移到前台 │
│ Task1: [A, B] │
│ Task2: [C] (singleInstance) ← C 独占 Task2 │
│ │
│ singleInstancePerTask (Android 12 新增): │
│ → 每个 Task 中最多一个实例 │
│ → 但可以在不同 Task 中有多个实例 │
│ │
├────────────────────────────────────────────────────────────────┤
│ │
│ 关键 Flag 处理: │
│ │
│ FLAG_ACTIVITY_NEW_TASK: │
│ → 如果目标 Activity 的 taskAffinity 有匹配的 Task → 用它 │
│ → 没有匹配 → 创建新 Task │
│ → 与 singleTask 类似但不清除栈顶 │
│ │
│ FLAG_ACTIVITY_CLEAR_TOP: │
│ → 如果目标 Activity 已在 Task 中 → 清除它上面所有 Activity │
│ → standard 模式: 连同自己也销毁再重建 │
│ → singleTop/singleTask: 保留自己, 调用 onNewIntent() │
│ │
│ FLAG_ACTIVITY_SINGLE_TOP: │
│ → 等同于 singleTop launchMode │
│ │
│ FLAG_ACTIVITY_CLEAR_TASK: │
│ → 清除整个 Task 中所有 Activity │
│ → 必须配合 FLAG_ACTIVITY_NEW_TASK 使用 │
└────────────────────────────────────────────────────────────────┘
Q10:taskAffinity 是什么?如何影响 Task 分配?
<activity
android:name=".DetailActivity"
android:taskAffinity="com.example.detail"
android:launchMode="singleTask" />
场景: allowTaskReparenting = true
Step 1: App A 启动 App B 的 Activity X (taskAffinity=B)
Task_A: [A1, X] ← X 暂时在 A 的 Task 中
Step 2: 用户从 Launcher 点击 App B 图标
AMS 发现 X 的 taskAffinity 属于 B
→ X 从 Task_A 迁移到 Task_B
Task_A: [A1]
Task_B: [X] ← X 回到了它 "亲和" 的 Task
五、ANR 机制
Q11:ANR 是怎么触发的?AMS 如何监控?
┌──────────────────────────────────────────────────────────────┐
│ ANR 超时监控机制 │
│ │
│ ┌─────────────────────────┬──────────────┬───────────────┐ │
│ │ 场景 │ 超时时间 │ 监控位置 │ │
│ ├─────────────────────────┼──────────────┼───────────────┤ │
│ │ InputEvent (触摸/按键) │ 5 秒 │ InputDispatcher│ │
│ │ BroadcastReceiver │ 前台 10s │ AMS │ │
│ │ (onReceive) │ 后台 60s │ BroadcastQueue│ │
│ │ Service │ 前台 20s │ AMS │ │
│ │ (onCreate/onStart等) │ 后台 200s │ ActiveServices │ │
│ │ ContentProvider │ 10 秒 │ AMS │ │
│ │ (publish) │ │ │ │
│ └─────────────────────────┴──────────────┴───────────────┘ │
└──────────────────────────────────────────────────────────────┘
Service ANR 监控原理(以 Service 为例):
AMS 侧:
┌─────────────────────────────────────────────┐
│ ActiveServices.realStartServiceLocked() │
│ │ │
│ ├── 1. 发送延迟消息 (定时炸弹) │
│ │ bumpServiceExecutingNoClearLocked() │
│ │ → mAm.mHandler.sendMessageDelayed(│
│ │ SERVICE_TIMEOUT_MSG, │
│ │ timeout) // 前台20s, 后台200s │
│ │ │
│ ├── 2. 通知 App 执行 Service │
│ │ app.thread.scheduleCreateService() │
│ │ │
│ └── 3. App 执行完后回调 │
│ serviceDoneExecutingLocked() │
│ → 移除延迟消息 (拆炸弹) │
│ mAm.mHandler.removeMessages( │
│ SERVICE_TIMEOUT_MSG) │
│ │
│ 如果超时消息触发: │
│ → serviceTimeout() │
│ → appNotResponding() → 弹出 ANR 对话框 │
│ → dump 信息到 /data/anr/traces.txt │
└─────────────────────────────────────────────┘
时间线:
──── 发送延迟消息 ──────────────────── 超时触发 ANR!
t0 t0 + 20s
│ │
└── App 必须在这之前完成 ──┘
并调用 serviceDoneExecuting()
移除延迟消息
Input ANR 监控 (InputDispatcher 层面, Native):
InputDispatcher.dispatchMotionLocked()
│
├── 找到目标 Window 的 Connection
│
├── 检查: 该 Connection 是否有未处理完的事件?
│ ├── 没有 → 正常分发, 记录分发时间
│ │
│ └── 有 → 检查已过去多长时间
│ ├── < 5s → 继续等待
│ └── ≥ 5s → 触发 ANR
│ → notifyAnr()
│ → AMS.inputDispatchingTimedOut()
│ → appNotResponding()
│
└── 另一种情况: 找不到目标 Window (focused window = null)
→ 等待 5s 后 ANR
Q12:ANR 发生后如何分析?
ANR 信息收集 (AMS.appNotResponding):
1. traces.txt (最重要)
/data/anr/traces.txt
├── 主线程堆栈 → 看当时在执行什么
├── 其他线程堆栈 → 看是否死锁/等待
└── 锁信息 → 看是否有锁竞争
2. main log
ActivityManager: ANR in com.example.app
ActivityManager: PID: 12345
ActivityManager: Reason: Input dispatching timed out
ActivityManager: CPU usage:
50% 12345/com.example.app: 48% user + 2% kernel
20% 567/system_server: 15% user + 5% kernel
分析步骤:
┌────────────────────────────────────────────────────┐
│ 1. 看 Reason → 确定 ANR 类型 │
│ Input dispatching / Broadcast / Service │
│ │
│ 2. 看 CPU usage │
│ ├── CPU 占用高 → 主线程做了耗时计算 │
│ ├── CPU 占用低 → 主线程被阻塞(锁/IO/IPC) │
│ └── 其他进程 CPU 高 → 系统繁忙导致调度延迟 │
│ │
│ 3. 看主线程堆栈 │
│ ├── 在等锁 → 找持锁线程 │
│ ├── 在 Binder 调用 → 对端阻塞 │
│ ├── 在 I/O 操作 → 主线程做了磁盘/网络 │
│ ├── 在 SharedPreferences → apply/commit 阻塞 │
│ └── 正常位置 → 可能是之前的耗时操作已完成 │
│ │
│ 4. 看是否死锁 │
│ 线程A: waiting to lock <0x1234> held by 线程B │
│ 线程B: waiting to lock <0x5678> held by 线程A │
└────────────────────────────────────────────────────┘
六、广播机制
Q13:广播的注册和发送流程是怎样的?
┌──────────────────────────────────────────────────────────────┐
│ 广播注册流程 │
│ │
│ 动态注册: │
│ context.registerReceiver(receiver, intentFilter) │
│ → ContextImpl.registerReceiverInternal() │
│ → AMS.registerReceiverWithFeature() │
│ → mRegisteredReceivers.put(receiver, ReceiverList) │
│ → mReceiverResolver.addFilter(BroadcastFilter) │
│ │
│ 静态注册: │
│ AndroidManifest.xml <receiver> │
│ → PMS 安装时解析 │
│ → PMS.mReceivers (PackageParser.Activity) │
│ → AMS 发送广播时查询 PMS │
│ │
│ 区别: │
│ ┌────────────┬───────────────┬──────────────────────────┐ │
│ │ │ 静态注册 │ 动态注册 │ │
│ ├────────────┼───────────────┼──────────────────────────┤ │
│ │ 注册时机 │ 安装时 │ 代码运行时 │ │
│ │ 存储位置 │ PMS │ AMS │ │
│ │ 生命周期 │ 常驻 │ 随组件生命周期 │ │
│ │ 优先收到 │ 后 │ 先 (有序广播中) │ │
│ │ Android 8+ │ 大部分隐式 │ 不受限制 │ │
│ │ │ 广播被限制 │ │ │
│ └────────────┴───────────────┴──────────────────────────┘ │
└──────────────────────────────────────────────────────────────┘
广播发送流程:
sendBroadcast(intent)
│
▼
AMS.broadcastIntentLocked()
│
├── 1. 解析 Intent, 找到匹配的 Receiver
│ ├── PMS 查找静态注册的 Receiver
│ └── AMS 查找动态注册的 Receiver
│
├── 2. 权限检查
│
├── 3. 构建 BroadcastRecord
│
└── 4. 加入 BroadcastQueue
│
├── 普通广播 → 并行分发 (所有Receiver同时收到)
│ → BroadcastQueue.scheduleBroadcastsLocked()
│ → processNextBroadcastLocked()
│ → 遍历所有 Receiver
│ → deliverToRegisteredReceiverLocked()
│ → app.thread.scheduleRegisteredReceiver()
│
└── 有序广播 → 串行分发 (按优先级逐个分发)
→ 等上一个处理完才发下一个
→ 可以 abortBroadcast() 截断
→ 每个 Receiver 有超时限制 (前台10s/后台60s)
两个队列:
foregroundQueue: 前台广播队列 (超时10s)
backgroundQueue: 后台广播队列 (超时60s)
七、Service 管理
Q14:Service 的启动和绑定在 AMS 中如何处理?
startService 流程:
┌─────────────────────────────────────────────┐
│ context.startService(intent) │
│ → AMS.startServiceLocked() │
│ → ActiveServices.startServiceLocked() │
│ │ │
│ ├── 1. 检索 ServiceRecord │
│ │ (PMS 解析 Intent 查找) │
│ │ │
│ ├── 2. 创建 ServiceRecord (如果不存在) │
│ │ │
│ ├── 3. 目标进程是否存在? │
│ │ ├── 不存在 → 先启动进程 │
│ │ └── 存在 ↓ │
│ │ │
│ ├── 4. realStartServiceLocked() │
│ │ → 发送超时消息 (20s/200s) │
│ │ → app.thread.scheduleCreate() │
│ │ → Service.onCreate() │
│ │ │
│ └── 5. sendServiceArgsLocked() │
│ → app.thread.scheduleService() │
│ → Service.onStartCommand() │
└─────────────────────────────────────────────┘
bindService 流程:
┌─────────────────────────────────────────────┐
│ context.bindService(intent, conn, flags) │
│ → AMS.bindServiceLocked() │
│ │ │
│ ├── 1. 查找/创建 ServiceRecord │
│ ├── 2. 创建 ConnectionRecord │
│ │ (关联 ServiceConnection 回调) │
│ ├── 3. 启动 Service (如果未启动) │
│ │ → onCreate() │
│ ├── 4. requestServiceBindingLocked() │
│ │ → app.thread.scheduleBindService()│
│ │ → Service.onBind() │
│ │ → AMS.publishServiceLocked() │
│ │ → 回调 conn.onServiceConnected│
│ │ (传回 IBinder) │
│ └── 5. 更新 OomAdj (绑定影响优先级) │
└─────────────────────────────────────────────┘
ServiceRecord 数据结构:
├── ComponentName (包名+类名)
├── ProcessRecord (所在进程)
├── Intent (启动意图)
├── bindings (Map<Intent.FilterComparison, IntentBindRecord>)
├── connections (所有绑定的 ConnectionRecord)
└── deliveredStarts (已分发的 start 请求)
八、ContentProvider 管理
Q15:ContentProvider 为什么能跨进程通信?AMS 在其中的角色?
ContentProvider 获取流程:
App A 调用 getContentResolver().query(uri, ...)
│
▼
ContentResolver.query()
→ acquireProvider()
→ ActivityThread.acquireProvider()
│
├── 1. 本地缓存查找 (mProviderMap)
│ → 找到 → 直接使用
│
└── 2. 向 AMS 请求
→ AMS.getContentProvider()
│
├── Provider 所在进程已启动?
│ ├── 是 → 直接返回 ContentProviderHolder
│ │ (包含 IContentProvider Binder 引用)
│ │
│ └── 否 → 启动目标进程
│ → 进程启动时自动 installProvider
│ → AMS.publishContentProviders()
│ → 等待 Provider 发布完成
│ → 返回 ContentProviderHolder
│
▼
拿到 IContentProvider (Binder 代理)
→ 通过 Binder 跨进程调用
→ query/insert/update/delete
→ 数据通过 CursorWindow (匿名共享内存) 传输
重要: ContentProvider 在 Application.onCreate() 之前初始化!
ActivityThread.handleBindApplication()
→ installContentProviders() // 先初始化 Provider
→ mInstrumentation.callApplicationOnCreate() // 后初始化 App
九、内存管理
Q16:AMS 如何管理应用内存?trimMemory 回调机制?
┌──────────────────────────────────────────────────────────────┐
│ AMS 内存管理 │
│ │
│ 触发时机: │
│ 系统内存不足 → LMK 根据 OomAdj 杀进程 │
│ Activity 状态变化 → AMS 更新 OomAdj │
│ AMS 定期执行 updateOomAdjLocked() │
│ │
│ updateOomAdjLocked() 流程: │
│ 1. 遍历所有 ProcessRecord │
│ 2. 根据进程中的组件状态计算新的 OomAdj │
│ ├── 有前台 Activity → 0 │
│ ├── 有可见 Activity → 100 │
│ ├── 有前台 Service → 200 │
│ ├── 正在执行 BroadcastReceiver → 0~300 │
│ ├── 有绑定关系 → 根据客户端 Adj 调整 │
│ └── 纯后台/空进程 → 900+ │
│ 3. 调用 ProcessList.setOomAdj() → 写入内核 │
│ 4. 如果进程应该被杀 → Process.killProcess() │
│ │
│ trimMemory 回调: │
│ AMS.appTrimMemory() │
│ → app.thread.scheduleTrimMemory(level) │
│ → Application.onTrimMemory(level) │
│ → 各组件 onTrimMemory() │
│ │
│ Level: │
│ ├── TRIM_MEMORY_UI_HIDDEN (20) ← UI不可见,释放UI资源 │
│ ├── TRIM_MEMORY_RUNNING_MODERATE ← 运行中,系统内存偏低 │
│ ├── TRIM_MEMORY_RUNNING_LOW ← 运行中,内存低 │
│ ├── TRIM_MEMORY_RUNNING_CRITICAL ← 运行中,即将被杀 │
│ ├── TRIM_MEMORY_BACKGROUND (40) ← 在后台,LRU列表头部 │
│ ├── TRIM_MEMORY_MODERATE (60) ← 在后台,LRU中部 │
│ └── TRIM_MEMORY_COMPLETE (80) ← 在后台,即将被杀 │
└──────────────────────────────────────────────────────────────┘
十、AMS 与 Binder
Q17:AMS 如何通过 Binder 与 App 通信?
┌──────────────────────────────────────────────────────────────────┐
│ AMS Binder 通信架构 │
│ │
│ App → AMS 方向 (App 调用系统服务): │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ App 进程 system_server 进程 │ │
│ │ │ │
│ │ IActivityManager.Stub.Proxy ──Binder──→ AMS │ │
│ │ (Proxy) IPC (Stub实现) │ │
│ │ │ │
│ │ 实际调用链: │ │
│ │ startActivity() │ │
│ │ → Instrumentation │ │
│ │ → ActivityTaskManager.getService() │ │
│ │ → IActivityTaskManager.Stub.Proxy │ │
│ │ .startActivity(...) │ │
│ │ → Binder 驱动 → ATMS.startActivity() │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
│ AMS → App 方向 (系统回调应用): │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ system_server 进程 App 进程 │ │
│ │ │ │
│ │ IApplicationThread ──Binder──→ ApplicationThread │ │
│ │ .Stub.Proxy IPC (Stub 实现) │ │
│ │ (ActivityThread 内部类)│ │
│ │ │ │
│ │ AMS 回调 App: │ │
│ │ app.thread.scheduleTransaction(...) │ │
│ │ → Binder 驱动 │ │
│ │ → ApplicationThread.scheduleTransaction() │ │
│ │ → Handler H.sendMessage() │ │
│ │ → 主线程处理 │ │
│ │ → TransactionExecutor.execute() │ │
│ │ → Activity.onCreate() / onResume() / ... │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
│ 关键 Binder 接口: │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ IActivityManager App → AMS (Activity/进程管理) │ │
│ │ IActivityTaskManager App → ATMS (Activity/Task) │ │
│ │ IApplicationThread AMS → App (生命周期回调) │ │
│ │ IContentProvider App ↔ App (跨进程数据) │ │
│ │ IServiceConnection AMS → App (Service绑定回调) │ │
│ │ IIntentReceiver AMS → App (广播回调) │ │
│ └────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────┘
十一、App 启动优化相关
Q18:冷启动/温启动/热启动的区别?AMS 的处理有何不同?
┌────────────────────────────────────────────────────────────────┐
│ 三种启动方式 │
├────────────────┬─────────────────┬─────────────────────────────┤
│ │ AMS 侧处理 │ App 侧处理 │
├────────────────┼─────────────────┼─────────────────────────────┤
│ 冷启动 │ 进程不存在 │ fork进程 │
│ (Cold Start) │ → startProcess │ → ActivityThread.main() │
│ │ → 等进程attach │ → Application.onCreate() │
│ │ → 再启动Activity │ → Activity.onCreate() │
│ │ 最慢: 全部重来 │ 全部重新初始化 │
├────────────────┼─────────────────┼─────────────────────────────┤
│ 温启动 │ 进程存在 │ Activity 已被销毁 │
│ (Warm Start) │ → 直接启动 │ → Activity.onCreate() │
│ │ Activity │ 重新创建 Activity │
│ │ 较快: 跳过进程创建│ 跳过 Application 初始化 │
├────────────────┼─────────────────┼─────────────────────────────┤
│ 热启动 │ 进程存在 │ Activity 在内存中 │
│ (Hot Start) │ Activity 在栈中 │ → Activity.onRestart() │
│ │ → 直接 resume │ → onStart() → onResume() │
│ │ 最快 │ 只需恢复到前台 │
└────────────────┴─────────────────┴─────────────────────────────┘
冷启动时间线 (AMS 视角):
t0: AMS 收到 startActivity 请求
t1: AMS.startProcessLocked() → 请求 Zygote fork
t2: Zygote fork 完成, 子进程 main() 启动
t3: ActivityThread.attach() → AMS.attachApplication()
t4: AMS 绑定 ProcessRecord, 下发 bindApplication
t5: App: Application.onCreate() 完成
t6: AMS.realStartActivityLocked() → 下发 LaunchActivity
t7: App: Activity.onCreate/onStart/onResume
t8: 第一帧绘制完成 (reportFullyDrawn)
优化目标: 缩短 t0 → t8 的总时间
Q19:AMS 如何判断启动超时?
Activity 启动超时检测:
AMS 在 realStartActivityLocked() 中:
→ 发送延迟消息 LAUNCH_TIMEOUT_MSG (10秒)
→ 如果 Activity 在 10s 内没有 resume → 超时处理
→ Activity 正常 resume 后 → 移除延迟消息
进程启动超时:
→ AMS.startProcessLocked() 后发延迟消息
→ PROC_START_TIMEOUT_MSG (10秒)
→ 如果进程 10s 内没有 attachApplication → 杀掉进程
十二、面试高频问题速查
┌──────────────────────────────────────────────────────────────┐
│ AMS 面试高频问题 & 考点 │
├──────────────────────────────────────────────────────────────┤
│ │
│ 基础篇: │
│ ① AMS 是什么? 在哪个进程? 什么时候启动的? │
│ ② Activity 启动流程 (重中之重, 必须能画出来) │
│ ③ App 进程创建流程 (Zygote fork) │
│ ④ Application 和 Activity 谁先创建? │
│ ⑤ AMS 如何与 App 通信? (Binder 双向) │
│ │
│ 原理篇: │
│ ⑥ LaunchMode 四种模式的区别及 AMS 处理逻辑 │
│ ⑦ Task、ActivityStack、ActivityRecord 关系 │
│ ⑧ FLAG_ACTIVITY_NEW_TASK 什么时候必须设? │
│ ⑨ taskAffinity 作用 │
│ ⑩ onNewIntent 什么时候调用? │
│ │
│ 进阶篇: │
│ ⑪ ANR 触发机制 (埋炸弹/拆炸弹) │
│ ⑫ 进程优先级 OomAdj 计算及 LMK 回收策略 │
│ ⑬ 冷启动/温启动/热启动区别 │
│ ⑭ ContentProvider 为什么最先初始化? (利用这个特性做了什么?) │
│ ⑮ Service 启动 vs 绑定 在 AMS 中的区别 │
│ │
│ 实战篇: │
│ ⑯ 如何分析 ANR? traces.txt 怎么看? │
│ ⑰ 进程保活方案及系统限制演进 │
│ ⑱ Activity A 启动 Activity B 的生命周期顺序 │
│ ⑲ 按 Home 键 vs 按 Back 键 的区别 (AMS 行为) │
│ ⑳ Android 10+ ATMS 拆分的原因和影响 │
│ │
│ 深度篇: │
│ ㉑ ClientTransaction 机制 (Android 9+) │
│ ㉒ Activity 生命周期回调在哪个线程? 怎么切过去的? │
│ ㉓ AMS 中的锁 (WindowManagerGlobalLock) │
│ ㉔ 多窗口/分屏/画中画 AMS 如何处理? │
│ ㉕ Binder 死亡通知 (DeathRecipient) AMS 如何感知进程死亡 │
└──────────────────────────────────────────────────────────────┘
十三、关键问题详答
Q18 补充:Activity A 启动 Activity B,生命周期顺序?
A.onPause() ← AMS 先让 A 暂停
│
▼ (AMS 收到 A paused 的通知)
B.onCreate()
B.onStart()
B.onResume() ← B 完全显示
│
▼ (AMS 发现 A 完全不可见了)
A.onStop() ← 最后才 stop A
为什么这个顺序?
┌──────────────────────────────────────────────────────┐
│ AMS 的逻辑: │
│ │
│ 1. resumeTopActivity() │
│ → 发现栈顶要显示 B, 但 A 还是 resumed 状态 │
│ → 先 pause A (schedulePauseActivity) │
│ │
│ 2. A.onPause() 执行完毕 │
│ → App 回调 AMS: activityPaused() │
│ → AMS 继续启动 B │
│ │
│ 3. B 创建并 resume │
│ → AMS: B 已经完全可见 │
│ → AMS: A 已经完全不可见 → stopActivityLocked(A) │
│ → A.onStop() │
│ │
│ 设计原因: │
│ - 保证在 A.onPause() 中保存的数据 │
│ 在 B.onCreate() 中可以读取 │
│ - onPause() 应该尽快完成, 否则影响 B 的启动速度 │
│ - onStop() 延后执行, 不阻塞新 Activity 的显示 │
└──────────────────────────────────────────────────────┘
Q:按 Home 键 vs 按 Back 键,AMS 行为区别?
┌──────────────────────────────────────────────────────────────┐
│ │
│ Home 键: │
│ → InputDispatcher 分发 KEYCODE_HOME │
│ → PhoneWindowManager 拦截 │
│ → 启动 Launcher (带 FLAG_ACTIVITY_NEW_TASK) │
│ → AMS: 当前 Activity → onPause → onStop │
│ → AMS: Activity 仍在 Task 栈中 (不销毁!) │
│ → 再次打开 App → onRestart → onStart → onResume (热启动) │
│ │
│ Back 键: │
│ → InputDispatcher 分发 KEYCODE_BACK │
│ → Activity.onBackPressed() │
│ → finish() → AMS.finishActivity() │
│ → AMS: Activity 从 Task 栈中移除 │
│ → Activity → onPause → onStop → onDestroy │
│ → 如果 Task 空了 → Task 也被移除 │
│ → 再次打开 App → 需要重新 onCreate (温/冷启动) │
│ │
│ 核心区别: │
│ ┌────────────┬───────────────────┬──────────────────────┐ │
│ │ │ Home 键 │ Back 键 │ │
│ ├────────────┼───────────────────┼──────────────────────┤ │
│ │ Activity │ 保留在栈中 │ 从栈中移除 + 销毁 │ │
│ │ onDestroy │ 不调用 │ 调用 │ │
│ │ Task │ 移到后台 │ 可能被清空 │ │
│ │ 再次进入 │ 热启动 (onRestart) │ 冷/温启动 (onCreate) │ │
│ │ 进程 │ 通常保留 │ 通常保留(但可能被回收) │ │
│ └────────────┴───────────────────┴──────────────────────┘ │
└──────────────────────────────────────────────────────────────┘
Q:ContentProvider 最先初始化的利用(Jetpack 的 App Startup)
Application 启动顺序:
ActivityThread.handleBindApplication()
│
├── 1. installContentProviders() ← 先初始化所有 Provider!
│ ├── Provider A.onCreate()
│ ├── Provider B.onCreate()
│ └── Provider C.onCreate()
│
└── 2. Application.onCreate() ← 后初始化 Application
利用这个特性:
┌──────────────────────────────────────────────────────────────┐
│ Jetpack App Startup (androidx.startup) │
│ │
│ 原来: 每个库注册一个 ContentProvider 来自动初始化 │
│ Firebase → FirebaseInitProvider │
│ WorkManager → WorkManagerInitializer │
│ Lifecycle → ProcessLifecycleOwnerInitializer │
│ → 太多 ContentProvider → 启动变慢! │
│ │
│ 现在: 合并为一个 InitializationProvider │
│ → 统一管理所有库的初始化 │
│ → 支持依赖排序 │
│ → 支持懒初始化 │
│ │
│ class MyInitializer : Initializer<MySDK> { │
│ override fun create(context: Context): MySDK { │
│ return MySDK.init(context) │
│ } │
│ override fun dependencies(): List<Class<Initializer<*>>>│
│ = listOf(WorkManagerInitializer::class.java) │
│ } │
└──────────────────────────────────────────────────────────────┘
Q:AMS 感知进程死亡 — Binder DeathRecipient
┌──────────────────────────────────────────────────────────────┐
│ Binder 死亡通知机制 │
│ │
│ App 进程 attach 到 AMS 时: │
│ AMS 获得 IApplicationThread (App 的 Binder 服务端) │
│ AMS 注册 DeathRecipient: │
│ appThread.asBinder().linkToDeath(deathRecipient, 0) │
│ │
│ App 进程异常退出 (crash/被杀): │
│ Binder 驱动检测到进程死亡 │
│ → 遍历该进程的所有 Binder 引用 │
│ → 通知所有注册了 DeathRecipient 的对端 │
│ → AMS.binderDied() 被回调 │
│ │
│ AMS 收到死亡通知后: │
│ appDiedLocked() │
│ ├── 清理 ProcessRecord │
│ ├── 清理 ActivityRecord (finish 所有 Activity) │
│ ├── 清理 ServiceRecord (停止所有 Service) │
│ ├── 清理 BroadcastRecord │
│ ├── 清理 ContentProvider (释放所有 Provider) │
│ ├── 通知 WMS 清理 Window │
│ └── 更新 OomAdj (其他进程的依赖可能变化) │
│ │
│ 如果 Service 设置了 START_STICKY: │
│ → AMS 会在之后尝试重新启动该 Service │
└──────────────────────────────────────────────────────────────┘
十四、AMS 重要源码文件导航
frameworks/base/services/core/java/com/android/server/am/
├── ActivityManagerService.java ← AMS 主类 (进程/Service/Broadcast)
├── ActiveServices.java ← Service 管理
├── BroadcastQueue.java ← 广播分发队列
├── ProcessRecord.java ← 进程记录
├── ProcessList.java ← 进程列表 & OomAdj
├── ContentProviderHelper.java ← Provider 管理
├── AppErrors.java ← ANR / Crash 处理
│
frameworks/base/services/core/java/com/android/server/wm/
├── ActivityTaskManagerService.java ← ATMS (Activity/Task)
├── ActivityStarter.java ← Activity 启动逻辑
├── ActivityRecord.java ← Activity 记录
├── Task.java ← Task (原 TaskRecord+ActivityStack)
├── RootWindowContainer.java ← 窗口容器根节点
├── ActivityStackSupervisor.java ← Stack 管理
│
frameworks/base/core/java/android/app/
├── ActivityThread.java ← App 主线程
├── ApplicationThread (内部类) ← AMS→App 的 Binder Stub
├── Instrumentation.java ← 生命周期中介
├── ClientTransactionHandler.java ← Transaction 处理
├── servertransaction/
│ ├── ClientTransaction.java ← 事务封装
│ ├── TransactionExecutor.java ← 事务执行器
│ ├── LaunchActivityItem.java ← 启动Activity的事务项
│ ├── ResumeActivityItem.java ← Resume事务项
│ ├── PauseActivityItem.java
│ ├── StopActivityItem.java
│ └── DestroyActivityItem.java
总结
AMS 面试核心知识点优先级:
★★★★★ 必须精通:
1. Activity 完整启动流程 (能画出跨进程调用图)
2. 进程创建流程 (Zygote fork)
3. ANR 机制 (埋炸弹/拆炸弹/分析方法)
4. LaunchMode + Task 管理
5. 生命周期回调机制 (ClientTransaction)
★★★★ 重点掌握:
6. OomAdj 与进程回收
7. Binder 双向通信 (IActivityManager ↔ IApplicationThread)
8. Service 启动/绑定流程
9. 广播注册/分发流程
10. 冷/温/热启动区别
★★★ 了解:
11. ATMS 拆分背景
12. ContentProvider 初始化顺序
13. DeathRecipient 机制
14. 多窗口/分屏处理
15. 进程保活演进