2. AMS核心类与数据结构解析:ActivityRecord、TaskRecord、ProcessRecord
ActivityManagerService(AMS)作为Android框架中管理Activity生命周期的核心服务,其内部数据结构的组织方式直接影响任务的调度、进程的分配以及用户交互的流畅性。本章深入剖析三个最关键的类:ActivityRecord(Activity记录)、TaskRecord(任务栈记录)和ProcessRecord(进程记录),理解它们之间的关联关系是定制AMS行为的基础。
2.1 三个核心类的角色与职责
AMS内部通过三大记录类来维护系统状态:
- ActivityRecord:描述一个具体的Activity实例,包含其标识、状态、所属进程、所在任务栈等信息。
- TaskRecord:描述一个任务(Task)的集合,即一组有顺序关系的Activity栈(通常称为“返回栈”)。每个TaskRecord维护一个
ArrayList<ActivityRecord>作为其成员栈。 - ProcessRecord:描述一个正在运行的Android应用进程,包含进程ID、UID、运行的Activity列表、服务列表、广播接收器等。
它们之间的关系可以用一句话概括:一个ProcessRecord可以包含多个TaskRecord;一个TaskRecord可以包含多个ActivityRecord;一个ActivityRecord只能属于一个TaskRecord,且运行在一个ProcessRecord中。
2.2 关键字段速查表
以下表格列出各记录类的核心字段及其在生产环境中的典型值范围或作用。定制AMS时,这些字段是Hook或拦截的常见目标。
| 类名 | 字段名 | 类型 | 说明 |
|---|---|---|---|
| ActivityRecord | int userId |
int | 所属用户ID(多用户场景) |
Intent intent |
Intent | 启动该Activity的原始Intent,包含action/data | |
ActivityInfo info |
ActivityInfo | 从PackageManager解析得到的Activity元信息(主题、启动模式、TaskAffinity等) | |
ProcessRecord app |
ProcessRecord | 当前运行该Activity的进程记录;若为空表示尚未附加到进程 | |
TaskRecord task |
TaskRecord | 所属的任务栈记录 | |
| TaskRecord | int taskId |
int | 全局唯一的任务ID(由TaskPersister分配) |
String affinity |
String | 任务亲和性字符串,通常与taskAffinity属性一致 |
|
ArrayList<ActivityRecord> mActivities |
ArrayList | 任务栈内所有ActivityRecord的有序列表(栈底到栈顶) | |
int mCallingUid |
int | 该任务创建者的UID,用于权限检查 | |
| ProcessRecord | int pid |
int | 进程PID |
int uid |
int | 应用UID | |
ArrayList<ActivityRecord> activities |
ArrayList | 该进程中所有已启动的ActivityRecord(不管属于哪个Task) | |
int curProcState |
int | 当前进程状态(如PROCESS_STATE_TOP、PROCESS_STATE_BOUND_FOREGROUND_SERVICE等) |
2.3 三者关联关系图
下方SVG展示了AMS中三条核心记录类的实例化关系以及它们与系统全局对象(如ActivityStackSupervisor/ActivityStack)的协作。注意每个ProcessRecord可挂多个TaskRecord,每个TaskRecord可挂多个ActivityRecord,并且ActivityRecord自身持有对所在TaskRecord和ProcessRecord的引用。
2.4 关键源码片段分析
以下是从Android 14(API 34)源码中摘录的三个类的精简定义,重点关注字段声明和构造逻辑。注意,为了定制方便,我们常常需要直接操作这些字段(例如通过反射或Binder拦截)。
2.4.1 ActivityRecord 核心构造
// frameworks/base/services/core/java/com/android/server/wm/ActivityRecord.java
public class ActivityRecord extends {
final int userId;
final Intent intent;
final ActivityInfo info;
final int launchMode; // 直接从 ActivityInfo 解析
// 运行时关联
ProcessRecord app;
TaskRecord task;
boolean visible; // 当前是否可见
int state; // 生命周期状态
public ActivityRecord(…, ActivityManagerService _service, Intent _intent,
ActivityInfo _info, …) {
userId = _intent.getUserId();
intent = _intent;
info = _info;
launchMode = info.launchMode;
// ...
}
}
2.4.2 TaskRecord 核心构造
// frameworks/base/services/core/java/com/android/server/wm/TaskRecord.java
public class TaskRecord {
final int taskId;
final String affinity;
final ArrayList<ActivityRecord> mActivities;
int mCallingUid;
int mCallingPid;
// 构造函数由 ActivityStackSupervisor 调用
public TaskRecord(..., int _taskId, String _affinity, ...) {
taskId = _taskId;
affinity = _affinity;
mActivities = new ArrayList<>();
// ...
}
}
2.4.3 ProcessRecord 核心构造
// frameworks/base/services/core/java/com/android/server/am/ProcessRecord.java
public class ProcessRecord {
final int pid;
final int uid;
final String processName;
ArrayList<ActivityRecord> activities; // 当前进程的所有Activity
ArrayList<ServiceRecord> services;
int curProcState; // 当前调度优先级
public ProcessRecord(..., ApplicationInfo _info, String _processName, int _uid) {
pid = -1; // 启动后由系统分配
uid = _uid;
processName = _processName;
activities = new ArrayList<>();
services = new ArrayList<>();
curProcState = PROCESS_STATE_IMPORTANT_BACKGROUND;
// ...
}
}
ActivityRecord.app 或 TaskRecord.mActivities 字段时,必须注意线程安全——AMS核心方法运行在 ActivityManagerService.mHandler 线程。如果是在Binder调用线程中修改,需要通过 mHandler.post() 或 synchronized(mService) 保证一致性。错误操作会导致 IndexOutOfBoundsException 或 NullPointerException,严重时引发SystemServer无响应(ANR)。
2.5 组件关联生命周期示例
以一个常见场景为例:用户从桌面点击应用图标,依次启动Activity A、B,然后按返回键回到桌面。下表展示关键时刻三个记录对象的变化:
| 时刻 | ProcessRecord | TaskRecord | ActivityRecord列表 |
|---|---|---|---|
| 1. 启动A | 新进程创建,pid=1234,activities=[AR_A] | 新任务taskId=5,mActivities=[AR_A] | AR_A.app=ProcessRecord#1234, AR_A.task=TaskRecord#5 |
| 2. 启动B | activities=[AR_A, AR_B] | mActivities=[AR_A, AR_B] | AR_B.app=ProcessRecord#1234, AR_B.task=TaskRecord#5 |
| 3. 按返回键B→A | activities=[AR_A](B被移除) | mActivities=[AR_A] | AR_B被finish,app=null,task=null |
| 4. 返回桌面 | curProcState变为PROCESS_STATE_TOP_SLEEPING | TaskRecord#5仍存在(未销毁) | AR_A状态变为STOPPED |
2.6 常见定制切入点
基于以上数据结构,以下列出AMS定制中常见的修改目标及对应的类字段:
- 调整Activity启动规则:重写
ActivityRecord.shouldBeVisible()或修改launchMode解析逻辑。 - 修改任务栈行为:在
TaskRecord.addActivityAtTop()中插入自定义栈策略(如限制最大深度、强制SingleTop)。 - 进程优先级管控:通过
ProcessRecord.curProcState的阈值调整,在内存压力下快速降低后台进程权重。 - 多用户/多显示场景:利用
ActivityRecord.userId和TaskRecord.affinity实现用户隔离或跨屏拖拽。
ActivityStackSupervisor.java 中的startActivityLocked() 方法,该方法同时操纵三个记录类,是理解三者交互流程的最佳入口。后续章节(第4~6章)将基于此处展开具体的定制代码实战。