3. AMS初始化流程与SystemServer集成:main函数、注册服务、binder线程池

AMS(ActivityManagerService)的初始化是SystemServer启动的核心环节。本章将剖析AMS从main函数入口到SystemServer集成,再到binder线程池建立的全过程。掌握这一流程后,你将能够理解AMS如何作为Android系统“大管家”在开机时完成就绪,并为后续的服务注册、Activity管理打下基础。

3.1 SystemServer.main() —— 启动入口

Zygote进程通过fork创建SystemServer进程后,执行的第一行Java代码是SystemServer.main()。该函数位于frameworks/base/services/java/com/android/server/SystemServer.java。其核心工作流如下表所示:

阶段 关键操作 线程/进程上下文
① 初始化SystemServer 调用SystemServer()构造,加载本地库android_servers 主线程
② 启动ServerThread 创建ServerThread线程并运行run() 主线程→子线程
③ 加载系统服务 在ServerThread.run()中按序启动引导服务、核心服务、其他服务 ServerThread
④ 注册服务到ServiceManager 调用ServiceManager.addService("activity", ams) ServerThread
⑤ 进入Looper循环 主线程(或ServerThread)开始消息循环,等待binder请求 ServerThread

关键点:SystemServer进程内部使用ServerThread(实为SystemServiceManager驱动的线程)来串行化服务启动,避免竞态。AMS必须在binder线程池就绪后才能被注册,否则其他进程无法通过binder调用到AMS。

// frameworks/base/services/java/com/android/server/SystemServer.java
public static void main(String[] args) {
    new SystemServer().run();
}

private void run() {
    // … 设置系统属性、加载本地库 …
    // 创建消息循环
    Looper.prepareMainLooper();

    // 初始化系统上下文
    createSystemContext();

    // 创建SystemServiceManager
    mSystemServiceManager = new SystemServiceManager(mSystemContext);

    // 启动服务
    try {
        startBootstrapServices();   // 包含AMS
        startCoreServices();
        startOtherServices();
    } catch (Throwable ex) { … }

    // 循环等待
    Looper.loop();
}

3.2 AMS的创建与ServiceManager注册

在startBootstrapServices()中,AMS通过mSystemServiceManager.startService(ActivityManagerService.class)被实例化并初始化。初始化完成后,立即向ServiceManager注册,使得其他进程可以通过ServiceManager.getService("activity")获取AMS的binder代理。

// SystemServer.java  startBootstrapServices()
private void startBootstrapServices() {
    // … 安装Provider …
    // 启动AMS
    mActivityManagerService = mSystemServiceManager.startService(
            ActivityManagerService.class);
    // 注册到ServiceManager
    ServiceManager.addService(Context.ACTIVITY_SERVICE, mActivityManagerService);
    // … 后续服务 …
}

注意:AMS的构造函数会触发大量初始化,包括进程记录、权限控制、内存管理等。如果此处抛出异常,SystemServer会直接崩溃导致设备重启。调试时可在ActivityManagerService.java构造函数中打日志,观察Binder线程池是否已启动。

3.3 Binder线程池初始化

Binder通信依赖线程池来处理跨进程请求。系统服务在加入ServiceManager之前,必须先确保ProcessState已经启动binder线程池。Android系统在Zygote阶段就已经通过ProcessState::self()->startThreadPool()启动了C++层的binder线程池,但Java层的BinderInternal也会在SystemServer中做最终确认。AMS的onStart()方法中调用了BinderInternal.setThreadPolicy(...)以及ProcessState::self()->setThreadPoolMaxThreadCount(...)来调整线程数。关键代码如下:

// ActivityManagerService.java  onStart()
@Override
public void onStart() {
    // 发布内部服务
    publishBinderService(Context.ACTIVITY_SERVICE, this);
    // 设置binder线程池最大线程数(通常为4)
    Process.setThreadPoolMaxThreadCount(4);
    // 启动binder线程池(如果尚未启动)
    BinderInternal.setThreadStarvationCheckEnabled(true);
    // … 其他初始化 …
}

原理说明:Binder线程池的默认大小为16(framework侧),但AMS服务由于高频调用,通常会通过setThreadPoolMaxThreadCount限制为4~8个线程,避免过多线程导致锁竞争。你可以通过Process.getThreadPoolMaxThreadCount()在运行时查看当前值。

3.4 完整初始化流程图

下图总结了AMS从SystemServer启动到Binder线程池就绪的完整流程:

AMS初始化与SystemServer集成流程 AMS初始化与SystemServer集成流程 Zygote fork SystemServer进程 SystemServer.main() run() -> ServerThread startBootstrapServices() 创建AMS实例 AMS.onStart() 设置binder线程池 ServiceManager.addService() 注册"activity"服务 Binder线程池 等待远程调用 说明: AMS必须在SystemServer的ServerThread中创建并注册,之后其他系统服务(如PackageManager、WindowManager) 才能通过binder与AMS交互。binder线程池的大小可根据设备负载动态调整。

3.5 关键代码与调试技巧

  • 验证AMS是否注册成功:在设备上执行 adb shell service list | grep activity,若能输出类似 Found 1 services: activity 则表示注册成功。
  • binder线程池状态监控:抓取trace时关注 Binder: thread pool 相关日志,若出现 Binder: thread pool starved 说明线程不够用,可增大setThreadPoolMaxThreadCount的值。
  • AMS初始化故障定位:如果设备在开机动画后反复重启,可抓取 logcat -b system,搜索 ActivityManagerService 或 SystemServer 异常堆栈。
// 查看当前binder线程池信息 (root权限)
adb shell su -c dumpsys activity | grep "binder"
// 通常输出类似:
// Binder: thread pool size: 8, max: 8, starved: 0

性能优化建议:在低内存设备上,可以将AMS的binder线程池上限从8调整为4,减少线程栈占用内存。调整位置:ActivityManagerService.java的onStart()方法中修改Process.setThreadPoolMaxThreadCount(4)。