一、 AMS 线程模型的演进史
AMS 的线程模型核心从未改变:Binder 线程池处理请求 + 专用 Looper 线程串行化任务。但其具体实现和类结构经历了几个关键阶段。
第一阶段:单体架构时代 (Android 5.0 - Android 9.0)
以 Android 7.0 (Nougat) 源码为例:
- 线程模型:
- SystemServer 主线程: 负责启动 AMS,但在启动后,AMS 的核心业务逻辑并不依赖此线程。
-
AMS 专用线程 ("ActivityManager"):
-
AMS 在构造函数中创建 mHandlerThread = new ServiceThread(TAG, ...)。
-
mHandler (即 MainHandler) 绑定的是这个 mHandlerThread 的 Looper。
-
-
作用: 处理广播超时、Service 生命周期调度、进程查杀等。
-
UI 线程 ("android.ui"):
-
UiHandler 绑定的是 UiThread 的 Looper。
-
作用: 仅处理系统级 UI(ANR 弹窗、“应用停止运行”弹窗)。
-
-
源码佐证 (Android 7.0 ActivityManagerService.java):
public ActivityManagerService(Context systemContext) {
// ...
// 创建名为 "ActivityManager" 的专用线程
mHandlerThread = new ServiceThread(TAG, Process.THREAD_PRIORITY_FOREGROUND, false);
mHandlerThread.start();
mHandler = new MainHandler(mHandlerThread.getLooper()); // <--- 关键点:MainHandler 不在 SystemServer 主线程
mUiHandler = new UiHandler(); // 内部使用 UiThread.get()
// ...
}
第二阶段:ATMS 分离时代 (Android 10 - Android 12)
Google 开始重构,将 Activity 的管理从 AMS 中剥离,成立 ActivityTaskManagerService (ATMS)。
- 变化特征:
-
AMS 依然保留自己的 ServiceThread ("ActivityManager") 和 MainHandler。
-
ATMS 引入了 mH (内部 Handler),且通常利用 android.display 线程或 android.ui 线程来处理部分窗口相关逻辑。
-
目的: 试图解耦 Activity 栈管理(重 UI/窗口)与 Service/ContentProvider 管理(重后台/IO)。
第三阶段:细粒度锁与并发优化 (Android 13/14+)
线程结构基本稳定,主要变化在于同步机制(锁的优化)。
-
当前状态:
-
AMS 依然运行在名为 ActivityManager 的 ServiceThread 上。
-
大量工作被分流到 BiometricThread, IoThread 等辅助线程。
-
引入了无锁数据结构和更细粒度的锁对象。
-
二、 AMS 的同步机制(核心修正)
这才是最复杂的部分。既然 MainHandler 一直都是独立的,那为什么我们总觉得 SystemServer 很“卡”?因为锁。
1. 锁对象的演进
- Android 9.0 及之前:一把大锁 (The Global Lock)
-
机制: synchronized(this)。
-
AMS 对象本身就是锁。任何 Binder 线程进入 AMS 的 API(如 startActivity),或者 MainHandler 处理消息,几乎都需要先拿到 this 锁。
-
后果: 即便 MainHandler 在独立线程,只要它拿着 AMS 锁(例如正在遍历 mProcessNames 列表),Binder 线程池里的 startActivity 请求就得等着。线程虽独立,但锁是共享的。
-
-
Android 10+:锁的分离 (AMS Lock vs. WM Lock)
-
机制:
-
AMS 锁: synchronized(this) 用于保护 Service, Provider, Broadcast, ProcessList。
-
WM 全局锁 (WindowManagerGlobalLock): 用于保护 Activity 栈、Window 布局。ATMS 和 WMS 共享这把锁。
-
-
后果: 启动 Service(AMS 锁)和 启动 Activity(WM 锁)在大部分情况下可以并发执行了,减少了竞争。
2. 死锁与 Watchdog 的监控对象
不同版本的 Watchdog 监控策略也侧面印证了线程模型:
-
Monitor 接口: AMS 实现了 Watchdog.Monitor。
-
监控逻辑: Watchdog 线程会定期请求 AMS 去获取它的锁。
-
如果 AMS 的 ServiceThread(即 MainHandler 所在线程)因为逻辑死循环卡死,Watchdog 即使能拿到锁也没用,因为 Monitor 检查通常包含 Handler 消息的派发检查。
-
如果 Binder 线程池因为死锁(如 AMS 等 WMS,WMS 等 AMS)卡死,Watchdog 尝试拿锁会超时,从而触发重启。
三、 总结:正确的 AMS 线程模型视图
1.MainHandler 所在的线程:
- 始终是独立的。自 Android 4.x/5.x 以来,它就运行在一个名为 "ActivityManager" 的 ServiceThread 中,绝不是 system_server 进程的主线程。
2.线程独立性:
-
system_server 主线程(UI Thread)
-
AMS 线程 (ActivityManager ServiceThread)
-
System UI 辅助线程 (android.ui ServiceThread)
-
它们三者在 OS 层面完全独立,拥有各自的 Looper 和 Stack。
3.同步的核心痛点:
-
虽然线程独立,但数据不独立。
-
MainHandler 处理消息时(如处理 SERVICE_TIMEOUT_MSG),需要 synchronized(AMS)。
-
UiHandler 弹出 ANR 框时,需要读取进程信息,往往也需要 synchronized(AMS)。
-
结论: 如果 AMS 线程因为逻辑错误(死循环)空转,UiHandler 不受影响。但如果 AMS 线程因为持锁阻塞(Waiting on I/O or other Locks),UiHandler 试图拿锁时也会被卡死。