29、AMS 源码导读:关键类源码分析

说实话,啃AMS源码这件事,我当年也觉得很痛苦。代码量巨大,类之间关系复杂,稍不留神就迷失在调用链里。但后来我发现一个窍门——抓住三个核心类,就能把整个Activity管理的骨架理清楚。

哪三个?ActivityManagerServiceActivityStackActivityRecord。今天我们就来拆开看看,它们各自扮演什么角色,又是怎么配合的。

ActivityManagerService:系统的大脑

AMS是整个Activity管理的总控中心。它负责什么?说白了,所有跟Activity生命周期、进程调度、任务栈管理相关的事情,最终都要经过它

我习惯把AMS想象成一个操作系统里的“大管家”。你启动一个App,它要检查权限、创建进程、通知Launcher动画、还要管理栈。事情多到爆炸。

来看一段核心代码,这是AMS处理startActivity的入口:

// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public final int startActivity(IApplicationThread caller, String callingPackage,
        Intent intent, String resolvedType, IBinder resultTo, String resultWho,
        int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
    return startActivityAsUser(caller, callingPackage, intent, resolvedType,
            resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions,
            UserHandle.getCallingUserId());
}

嗯,这里只是转调。真正干活的是startActivityAsUser,它会经过一系列权限检查、进程判断,最后交给ActivityStackSupervisor去处理。

关键点:AMS本身不直接操作Activity栈,它通过ActivityStackSupervisor来协调各个ActivityStack。这种分层设计,让AMS可以专注于“决策”,而把“执行”下放。

我在项目中遇到过一个问题:App启动时偶现ANR,查了半天发现是AMS主线程被一个广播阻塞了。你看,AMS虽然是大脑,但它也是单线程处理消息的,任何耗时操作都会卡住整个系统

ActivityStack:栈的管理者

ActivityStack,顾名思义,就是管理Activity栈的。但别小看它,它不只是个“栈容器”。

每个ActivityStack对应一种“栈类型”。比如:

  • HOME_STACK:桌面Launcher所在的栈
  • FULLSCREEN_STACK:全屏应用栈
  • FREEFORM_STACK:自由窗口模式栈

每个栈里维护着一组TaskRecord,而每个TaskRecord里又包含多个ActivityRecord。这个层级关系,我画了张图:

ActivityManagerService ActivityStackSupervisor HOME_STACK FULLSCREEN_STACK FREEFORM_STACK TaskRecord TaskRecord TaskRecord ActivityRecord ActivityRecord ActivityRecord ActivityRecord ActivityRecord ActivityRecord ActivityRecord ActivityRecord ActivityRecord

你看,这个层级关系非常清晰。AMS通过Supervisor管理多个Stack,每个Stack管理多个Task,每个Task管理多个ActivityRecord。

ActivityStack里有个重要的方法——resumeTopActivityInnerLocked。这个方法负责把栈顶的Activity恢复出来。我当年调试一个分屏bug时,就是在这里加了日志,才发现栈顶Activity的状态判断出了问题。

// frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
    // 找到栈顶的ActivityRecord
    ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
    if (next == null) {
        // 栈空了,启动桌面
        return resumeHomeActivityLocked(prev, "noMoreActivities");
    }
    // ... 省略大量状态判断和生命周期调用
}

个人经验:调试栈相关问题时,重点关注topRunningActivityLockedresumeTopActivityInnerLocked这两个方法。它们几乎涵盖了所有“栈顶切换”的场景。

ActivityRecord:每个Activity的“身份证”

ActivityRecord是什么?它不是一个Activity实例,而是AMS用来描述一个Activity的元数据对象。每个Activity在AMS里都对应一个ActivityRecord。

它里面记录了什么?我列一下关键字段:

字段 类型 说明
intent Intent 启动该Activity的Intent
state ActivityState 当前生命周期状态(INITIAL、RESUMED、PAUSED等)
app ProcessRecord 所属进程
task TaskRecord 所属任务栈
launchMode int 启动模式(standard、singleTop等)
visible boolean 是否可见

为什么说它是“身份证”?因为AMS判断两个Activity是否相同,就是通过比较ActivityRecord的intentlaunchMode。比如singleTop模式下,如果栈顶已经有一个相同Intent的ActivityRecord,就不会新建,而是复用。

来看一段ActivityRecord的构造方法:

// frameworks/base/services/core/java/com/android/server/am/ActivityRecord.java
ActivityRecord(ActivityManagerService _service, ProcessRecord _caller,
        int _launchedFromPid, int _launchedFromUid, String _launchedFromPackage,
        Intent _intent, String _resolvedType, ActivityInfo aInfo,
        Configuration _configuration, ActivityRecord _resultTo,
        String _resultWho, int _reqCode, boolean _componentSpecified,
        boolean _rootVoiceInteraction, ActivityStackSupervisor supervisor,
        ActivityOptions options, ActivityRecord sourceRecord) {
    service = _service;
    intent = _intent;
    info = aInfo;
    // ... 初始化一堆字段
    state = ActivityState.INITIALIZING;
}

嗯,这里有个细节:state初始值是INITIALIZING。之后AMS会通过scheduleLaunchActivity把它变成INITIAL,再通过生命周期回调一步步推进。

避坑指南:我曾经遇到一个诡异的问题——App切到后台再切回来,界面卡死了。查到最后发现是ActivityRecord的state在某个异常路径下被设置成了STOPPING,但对应的Activity线程根本没收到stop信号。结果AMS一直等,等到超时。所以,ActivityRecord的状态机必须严格同步,任何一步出错都会导致后续流程紊乱。

三个类如何协作?

我举个例子,你就能明白它们是怎么配合的了。

假设你点击桌面图标启动一个App:

  1. Launcher进程通过Binder调用AMS的startActivity
  2. AMS检查权限、解析Intent,创建ActivityRecord
  3. AMS通过ActivityStackSupervisor找到合适的ActivityStack
  4. ActivityStack把ActivityRecord压入栈顶,调用resumeTopActivityInnerLocked
  5. AMS通知Zygote进程fork出App进程
  6. App进程创建Activity实例,绑定到ActivityRecord上
  7. ActivityRecord的state一路从INITIALIZING走到RESUMED

整个过程,AMS是决策者,ActivityStack是栈管理者,ActivityRecord是状态记录者。三者缺一不可。

总结一下:读AMS源码,别一头扎进细节里。先理清这三个类的关系,你就掌握了Activity管理的“骨架”。剩下的,都是在这个骨架上添砖加瓦。

我个人习惯是,每读一个类,先画它的状态机或类关系图。画着画着,很多疑惑就自然解开了。你也不妨试试。


公众号:蓝海资料掘金营,微信deep3321