Android ActivityManagerService 笔记

4 阅读6分钟

ActivityManagerService(简称AMS)是Android系统中最核心、最复杂的服务,没有之一。它运行在SystemServer进程,掌管着四大组件的生命周期、进程的创建与调度、任务栈的管理以及系统状态监控。理解AMS,基本上就抓住了Android多任务机制的命脉。

下面我从五个维度展开,由浅入深帮你构建对AMS的完整认知:

一、AMS的定位与核心职责

它不是什么“管理器”,而是Android的“操作系统内核”。AMS本质上是一个系统级的状态机,协调着应用进程、系统服务、硬件资源之间的所有交互。具体职责分为四块:

职责维度核心作用关键表现
组件生命周期管理决定四大组件何时生、何时死startActivity最终由AMS校验并调度;sendBroadcast由AMS分发给接收器
进程管理决定进程何时创建、何时被杀应用进程由AMS请求Zygote孵化;低内存时AMS根据LRU列表杀进程
任务栈管理维护用户操作的历史堆栈记录ActivityRecord与TaskRecord的归属关系,处理singleTask等启动模式
系统状态监控感知内存、焦点、旋转等状态mResumedActivity变化时触发窗口焦点切换、暂停旧Activity

注意区分:应用层常用的ActivityManager只是一个“API壳”,它通过Binder与AMS通信,真正的决策者永远是SystemServer进程中的AMS实例。

二、架构演进:从代理模式到AIDL直通

AMS的通信架构在Android 8.0(API 26)发生了重大重构。如果你看过老文章,经常会提到ActivityManagerProxy(AMP)和ActivityManagerNative(AMN),但新版本已完全弃用。

📱 旧架构(Android 7.1及更低)

  • AMN(服务端存根):继承Binder,实现IActivityManager接口。
  • AMP(客户端代理):AMN的内部类,将方法调用打包进Parcel通过Binder驱动发送。
  • AMS(实际实现):继承AMN,重写业务方法。
  • 缺陷:手动编写Parcel打包/解包代码,易错且维护成本高。

📲 新架构(Android 8.0+)

  • 直接使用AIDLIActivityManager.aidl编译生成StubProxy
  • AMS继承IActivityManager.Stub,不再需要AMN/AMP这一层手工封装。
  • 优点:编译器检查、代码简洁、与标准Android接口定义语言统一。

当前现状:现在分析AMS源码,你会看到ActivityManagerService.java直接extends IActivityManager.Stub,跨进程通信逻辑由AIDL框架自动生成。这一点很多旧教程都未更新,需要特别注意。

三、启动与初始化:SystemServer的三大引导服务之一

AMS是在系统启动早期,由SystemServer进程创建的。整个过程分为三步:

  1. 创建实例SystemServiceManager.startService(ActivityManagerService.Lifecycle.class)Lifecycle是AMS的静态内部类,继承自SystemService,其构造函数中new ActivityManagerService(...)完成对象创建。

  2. 注册服务ServiceManager.addService(Context.ACTIVITY_SERVICE, ams)。将AMS注册到Binder驱动上下文,此后任何进程通过ServiceManager.getService()拿到Binder引用,即可与AMS通信。

  3. 启动准备ams.start()ams.systemReady()。前者完成进程组初始化;后者在系统核心服务就绪后调用,会恢复上次关机时未关闭的Activity、发送SYSTEM_READY广播。

关键特征:AMS是引导服务(Boot Service),与PackageManagerServicePowerManagerService同级,必须在系统UI启动前完全就绪。

四、核心数据结构:AMS靠四张“表”管理世界

AMS本身并不直接持有Activity对象,它维护的是镜像状态对象。这四个类你需要刻在脑子里:

数据结构作用存储位置对应关系
ProcessRecord进程记录mProcessNames一个应用进程对应一个实例
ActivityRecordActivity记录mActivityStarter内部一个Activity实例对应一个记录
TaskRecord任务栈ActivityStack一组ActivityRecord的集合
ActivityStack栈管理单元mActivityStacks显示屏(分屏时多个Stack)

运作逻辑

  • 当你想启动ActivityB,AMS先查ProcessRecord判断进程是否存在;
  • 若存在,再根据ActivityRecordTaskRecord计算应该放入哪个栈、是否复用栈顶;
  • 所有栈由ActivityStackSupervisor统一调度。

内存阈值:系统缓存的最大Activity数量默认为MAX_ACTIVITIES=20,最近任务记录默认为MAX_RECENT_TASKS=20,暂停超时为PAUSE_TIMEOUT=500ms

五、实战串讲:一次完整的Activity启动流程

把前面的知识点串起来,看一次跨应用启动的全过程(如从微信打开支付宝扫码页):

Step 1:发起请求(客户端进程)
微信调用startActivity(intent)。这个调用最终通过Instrumentation.execStartActivity()ActivityManager.getService().startActivity()。这里的getService()返回的就是AMS在微信进程的Binder代理对象IActivityManager.Stub.Proxy)。

Step 2:AMS预处理(SystemServer进程)
AMS收到Binder请求,执行startActivityAsUser()。首先合法性校验:Intent能否解析、调用方有无权限。然后计算栈:判断支付宝Activity的启动模式(如singleTask),决定复用已有栈还是新建TaskRecord。

Step 3:暂停源Activity
AMS找到当前有焦点的Activity(微信聊天页),调用其schedulePauseActivity()(通过ApplicationThread代理)。这是一个同步阻塞过程,超时500ms未响应则强制结束。

Step 4:进程孵化(如需)
若支付宝进程未运行,AMS向Zygote发送fork请求。Zygote收到Socket命令,fork()出新进程,并反射调用ActivityThread.main()。新进程启动后向AMS注册ApplicationThread,完成初始化。

Step 5:创建Activity实例
AMS通过支付宝进程的ApplicationThread代理,调用scheduleLaunchActivity()。支付宝主线程收到消息,反射构造Activity对象,依次执行onCreate()onStart()onResume()。渲染完成后通过activityIdle()通知AMS“我已可见”。

Step 6:状态收尾
AMS更新内部状态:将支付宝ActivityRecord设为mResumedActivity,将微信ActivityRecord暂停;更新最近任务列表;可能触发低内存杀进程(如清理空的旅游App进程)。

至此,一个Activity的生命周期跨越了至少三个进程(微信、SystemServer、支付宝),全程由AMS调度。

六、开发层面的启示

理解AMS不是为了手写Framework,而是帮你写出更稳定的应用

  1. 进程被杀不是Bug,是AMS的正常管理。不要在全局变量里存必须持久化的数据。
  2. 冷启动慢,根源在于AMS需要走完进程孵化、ActivityRecord创建、渲染测量这一整套流水线。优化方向是减少主线程阻塞,让activityIdle()尽早回调。
  3. 启动模式冲突时,以Flag为准。即使Manifest设置singleTask,代码里加FLAG_ACTIVITY_NEW_TASK也会生效。
  4. 调试利器:通过adb shell dumpsys activity可查看AMS内部所有的ActivityRecord、TaskRecord、进程优先级。这是定位栈混乱、页面不显示问题的终极手段。