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+)
- 直接使用AIDL:
IActivityManager.aidl编译生成Stub和Proxy。 - AMS继承
IActivityManager.Stub,不再需要AMN/AMP这一层手工封装。 - 优点:编译器检查、代码简洁、与标准Android接口定义语言统一。
当前现状:现在分析AMS源码,你会看到ActivityManagerService.java直接extends IActivityManager.Stub,跨进程通信逻辑由AIDL框架自动生成。这一点很多旧教程都未更新,需要特别注意。
三、启动与初始化:SystemServer的三大引导服务之一
AMS是在系统启动早期,由SystemServer进程创建的。整个过程分为三步:
-
创建实例:
SystemServiceManager.startService(ActivityManagerService.Lifecycle.class)。Lifecycle是AMS的静态内部类,继承自SystemService,其构造函数中new ActivityManagerService(...)完成对象创建。 -
注册服务:
ServiceManager.addService(Context.ACTIVITY_SERVICE, ams)。将AMS注册到Binder驱动上下文,此后任何进程通过ServiceManager.getService()拿到Binder引用,即可与AMS通信。 -
启动准备:
ams.start()和ams.systemReady()。前者完成进程组初始化;后者在系统核心服务就绪后调用,会恢复上次关机时未关闭的Activity、发送SYSTEM_READY广播。
关键特征:AMS是引导服务(Boot Service),与PackageManagerService、PowerManagerService同级,必须在系统UI启动前完全就绪。
四、核心数据结构:AMS靠四张“表”管理世界
AMS本身并不直接持有Activity对象,它维护的是镜像状态对象。这四个类你需要刻在脑子里:
| 数据结构 | 作用 | 存储位置 | 对应关系 |
|---|---|---|---|
ProcessRecord | 进程记录 | mProcessNames | 一个应用进程对应一个实例 |
ActivityRecord | Activity记录 | mActivityStarter内部 | 一个Activity实例对应一个记录 |
TaskRecord | 任务栈 | ActivityStack | 一组ActivityRecord的集合 |
ActivityStack | 栈管理单元 | mActivityStacks | 显示屏(分屏时多个Stack) |
运作逻辑:
- 当你想启动
ActivityB,AMS先查ProcessRecord判断进程是否存在; - 若存在,再根据
ActivityRecord和TaskRecord计算应该放入哪个栈、是否复用栈顶; - 所有栈由
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,而是帮你写出更稳定的应用:
- 进程被杀不是Bug,是AMS的正常管理。不要在全局变量里存必须持久化的数据。
- 冷启动慢,根源在于AMS需要走完进程孵化、ActivityRecord创建、渲染测量这一整套流水线。优化方向是减少主线程阻塞,让
activityIdle()尽早回调。 - 启动模式冲突时,以Flag为准。即使Manifest设置
singleTask,代码里加FLAG_ACTIVITY_NEW_TASK也会生效。 - 调试利器:通过
adb shell dumpsys activity可查看AMS内部所有的ActivityRecord、TaskRecord、进程优先级。这是定位栈混乱、页面不显示问题的终极手段。