第3章:startActivity启动流程源码剖析:从AMS到ActivityRecord的完整链路

3.1 流程概述

startActivity 的启动过程远不止表面上的 Activity 跳转。从应用进程发起请求,通过 Binder 跨进程通信到达系统服务端 SystemServer 中的 ActivityManagerService(AMS),再由 AMS 执行权限校验、进程管理、任务栈管理、生命周期调度等一系列核心决策,最终生成一个代表本次启动目标的 ActivityRecord 对象。本章将带领你沿着这个路径,逐层剖析关键源码,掌握整个链路的骨架。

3.2 调用入口:Instrumentation.execStartActivity

无论在 Activity 中调用 startActivity(Intent),还是通过 Context.startActivity,最终都会集中到 Instrumentation 类的 execStartActivity 方法。这个方法是客户端侧向 AMS 发起请求的最后一站。

// frameworks/base/core/java/android/app/Instrumentation.java
public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder , Activity target,
        Intent intent, int requestCode, Bundle options) {
    ...
    try {
        // 通过 ActivityManagerNative.getDefault() 获取 AMS 的 Binder 代理
        int result = ActivityManagerNative.getDefault()
            .startActivity(whoThread, who.getBasePackageName(), intent,
                    intent.resolveTypeIfNeeded(who.getContentResolver()),
                    , target != null ? target.mEmbeddedID : null,
                    requestCode, 0, null, options);
        // 检查 result 并返回
        checkStartActivityResult(result, intent);
    } catch (RemoteException e) {
        throw new RuntimeException("Failure from system", e);
    }
    return null;
}

关键链路节点:该方法内部通过 ActivityManagerNative.getDefault() —— 即 IActivityManager.Stub.asInterface(ServiceManager.getService("activity")) —— 获取 AMS 的 Binder 代理对象。随后调用的 startActivity 实际上已经跨入了 SystemServer 进程。

3.3 AMS 侧接收请求:startActivity→startActivityAsUser

Binder 驱动将请求序列化后传输到 SystemServer 进程,AMS 的 startActivity 方法被唤醒。该方法是整个流程的调度枢纽,它经过一系列参数检查和用户身份确认,最终调用内部的 startActivityAsUser。

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

@Override
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
        Intent intent, String resolvedType, IBinder resultTo,
        String resultWho, int requestCode, int startFlags,
        ProfilerInfo profilerInfo, Bundle options, int userId) {
    // 检查调用进程是否有发起该 Intent 的权限
    enforceNotIsolatedCaller("startActivityAsUser");
    userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
                userId, false, ALLOW_NON_FULL, "startActivityAsUser", null);
    // 此处进入 ActivityStarter 进行下一步决策
    return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
            resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
            profilerInfo, null, null, options, false, userId, null, null);
}
关键点:AMS 并不直接处理启动决策,而是将任务委托给了 ActivityStarter 组件。ActivityStarter 负责解析 Intent、检查 Activity 是否存在、计算启动标志位、以及创建 ActivityRecord 对象。

3.4 ActivityStarter:启动策略的决策引擎

ActivityStarter 内部维护了一套复杂的启动规则,包括 FLAG_ACTIVITY_NEW_TASK、taskAffinity、启动模式(launchMode)等。核心入口是 startActivityMayWait,该方法首先调用 PackageManagerService 解析 Intent。

// frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java
final int startActivityMayWait(...) {
    ...
    // 1. Intent 解析,获取 ActivityInfo
    ActivityInfo aInfo = resolveActivity(intent, rInfo, startFlags, profilerInfo);
    if (aInfo == null) {
        // 返回错误:ActivityNotFound
        return ActivityManager.START_INTENT_NOT_RESOLVED;
    }
    // 2. 创建 ActivityRecord 前的参数准备
    ActivityOptions activityOptions = ActivityOptions.fromBundle(options);
    ...
    // 3. 调用 startActivity 进入真正的决策与执行
    int res = startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo,
            voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid,
            callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options,
            false, componentSpecified, outRecord, activityOptions, inTask, ...);
    return res;
}

经过解析后,ActivityStarter 会调用内部的 startActivity 方法(重载),在此方法中经过安全校验、进程存活检查、以及启动模式确认后,最终执行到 startActivityUnchecked 方法。该方法根据 Intent 的标志和 Activity 的启动模式,决定是将启动新 Activity、复用栈顶、还是入栈到 Existing 任务。

启动模式ActivityStarter 决策行为常见影响
Standard默认创建新实例,入栈到启动者的任务栈可以多次创建相同 Activity
SingleTop如果目标 Activity 已是栈顶,则复用;否则创建新实例避免栈顶重复打开
SingleTask检查是否存在任务栈,存在则复用并清空栈上方的 Activity全局单例,启动时其他 Activity 会被出栈
SingleInstance独立的任务栈,且整个栈只能有该 Activity独立于其他应用的栈结构

3.5 ActivityRecord 的诞生

ActivityRecord 是 AMS 中代表一个具体 Activity 实例的“元数据对象”,它封装了包名、类名、intent、、进程信息、任务栈信息、生命周期状态等所有必要数据。ActivityStarter 在 startActivityUnchecked 中通过 ActivityStackSupervisor 的 startActivityLocked 方法创建该对象。

// frameworks/base/services/core/java/com/android/server/am/ActivityRecord.java
ActivityRecord(ActivityManagerService _service, ProcessRecord _caller,
        int _launchedFromUid, String _launchedFromPackage, Intent _intent,
        String _resolvedType, ActivityInfo aInfo, Configuration _configuration,
        ActivityRecord _resultTo, String _resultWho, int _reqCode,
        boolean _componentSpecified, ActivityRecord _sourceRecord,
        ActivityStack _activityStack, ActivityOptions options, ActivityRecord _sourceRecord2) {
    service = _service;
    intent = _intent;
    info = aInfo;
    userId = UserHandle.getUserId(aInfo.applicationInfo.uid);
    ...
    // 生成一个 32 位的唯一标识符  用于 Binder 通信
    appToken = new (this);
    ...
}
重要数据结构:ActivityRecord 内部持有 appToken 字段,该字段是一个 Binder 对象,Activity 端通过 与 AMS 通信,AMS 通过 反查找到对应的 ActivityRecord。

3.6 从 AMS 到目标进程:阶段小结与流程图

从应用程序调用 startActivity 到 AMS 内部创建 ActivityRecord,整个过程可以抽象为以下 6 个阶段。下图展示了这个完整的时序与核心节点。

核心脉络: 调用链始终遵循“应用进程 → Binder 驱动 → AMS(SystemServer)→ ActivityStarter → ActivityStackSupervisor → ActivityRecord”。任何边界控制(如权限拦截、冷启动中断、启动次数限制)都可以在这条链路的特定节点注入。
startActivity 从调用到 ActivityRecord 的完整链路 应用进程:startActivity Instrumentation.execStartActivity Binder (IActivityManager) AMS.startActivity ActivityStarter.startActivityMayWait PMS.resolveActivity → ActivityInfo startActivityUnchecked(模式决策) ActivityRecord 对象创建 说明 AMS 并不直接创建 ActivityRecord, 而是通过 ActivityStarter 和 ActivityStackSupervisor 逐层决策。 PMS 角色 resolveActivity 会查询已安装 应用,返回目标 ActivityInfo。

3.7 完整调用链代码结构

以下是关键调用链路径,每个方法都落在对应类的内部。你可以使用 Android Studio 的 Show Call Hierarchy 快速验证这些调用关系。

客户端:
Instrumentation.execStartActivity()
  → ActivityManagerNative.getDefault().startActivity()   // Binder 调用
    ↓ Binder 驱动
服务端:
ActivityManagerService.startActivity()
  → ActivityManagerService.startActivityAsUser()
    → ActivityStarter.startActivityMayWait()
      → ActivityStarter.startActivity()                  // 重载方法
        → ActivityStarter.startActivityUnchecked()
          → ActivityStackSupervisor.startActivityLocked()
            → new ActivityRecord(service, caller, intent, aInfo, ...)
常见误区:开发者经常误认为 ActivityRecord 是在 AMS 的 startActivity 阶段直接创建的。实际上,在 startActivityMayWait 之前只解析出了 ActivityInfo,而真正的对象生成是在 startActivityUnchecked 处理完启动模式、任务栈复用逻辑之后,由 ActivityStackSupervisor 负责生成。

3.8 调试与验证方法

你可以在 ActivityStackSupervisor.startActivityLocked 中打印日志,确认 ActivityRecord 创建时的详细信息:

// 添加调试日志(需在 userdebug 或 eng 版本下测试)
if (DEBUG_STACK) {
    Slog.d(TAG, "Creating ActivityRecord: pkg=" + aInfo.packageName
            + ", cls=" + aInfo.name
            + ", userId=" + userId
            + ", resultTo=" + (resultTo != null ? resultTo.shortComponentName : "null")
            + ", callingPid=" + _caller.pid);
}

你也可以通过 dumpsys activity activities 命令实时查看当前系统中所有 ActivityRecord 的状态:

adb shell dumpsys activity activities | grep -E "ActivityRecord|Hist"
# 输出示例:
#   * ActivityRecord{76c1b27 u0 com.example.app/.MainActivity t123}
#     intent={act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER]}
#     processName=com.example.app
#     launchedFromUid=10123
#     state=RESUMED

ActivityRecord 的 state 字段表明当前生命周期阶段(INITIALIZING → RESUMED ↔ PAUSED → STOPPED → DESTROYED)。通过监控 dumpsys 输出,你可以判断定制的边界控制逻辑是否在 ActivityRecord 创建之前或创建时被正确触发。

边界控制的插入点建议:如果你想定制启动边界(例如:限制某个包名下 Activity 的并发数、跳过特定 Intent 的启动),推荐在 ActivityStarter.startActivityMayWait 执行 after PMS 解析但 before 创建 ActivityRecord 的阶段插入拦截逻辑。此时已获取到完整的 ActivityInfo,但还未生成 Record,不会污染栈结构。