Activity 启动流程(二)—— AMS 处理阶段

418 阅读7分钟

前言

启动流程梳理:

  1. Activity 启动流程(一)—— Launcher 阶段
  2. Activity 启动流程(二)—— AMS 处理阶段
  3. Activity 启动流程(三)—— 应用程序进程启动阶段
  4. Activity 启动流程(四)—— ActivityThread 初始化阶段
  5. Activity 启动流程(五)—— Activity 启动阶段

代码基于 android-14.0.0_r9

从 Android 10 开始,Activity 启动主链已经拆分到 ATMS / WM 侧:ActivityTaskManagerService 负责入口与裁决,ActivityStarter 负责启动决策,RootWindowContainer / Task 负责把目标 Activity 推到可恢复路径上。

1. 一句话总览

这一阶段的核心不是“把进程真正拉起来”或“让客户端立刻执行 onCreate()”,而是:系统侧先接住启动请求,做安全与用户校验,组装 ActivityStarter,创建或复用 Task,挂载 ActivityRecord,然后尝试恢复目标顶部 Activity;如果发现目标进程还没起来,再把请求异步交给进程启动链路。

主链路如下:

ActivityTaskManagerService.startActivityAsUser()ActivityStartController.obtainStarter()ActivityStarter.execute()executeRequest()startActivityUnchecked()startActivityInner()RootWindowContainer.resumeFocusedTasksTopActivities()Task.resumeTopActivityUncheckedLocked()TaskFragment.resumeTopActivity()ActivityTaskSupervisor.startSpecificActivity() / mAtmService.startProcessAsync()

flowchart LR
    A[ATMS.startActivityAsUser]
    B[ActivityStartController.obtainStarter]
    C[ActivityStarter.execute / executeRequest]
    D[创建 ActivityRecord]
    E[复用或创建 Task]
    F[resumeFocusedTasksTopActivities]
    G{目标进程是否已存在}
    H[发送 Resume 事务给现有进程]
    I[startSpecificActivity]
    J[startProcessAsync 异步交接]

    A --> B --> C --> D --> E --> F --> G
    G -- 已存在 --> H
    G -- 不存在 --> I --> J

这条链路里,ATMS/WM 做的是“系统侧裁决与挂载”;真正的进程创建,从 startProcessAsync() 之后才进入下一篇。

2. AMS 处理阶段源码分析

2.1 入口收口:ATMS 先做调用方校验,再把请求交给 ActivityStarter

Launcher 侧 Binder 调用最终会进入 ActivityTaskManagerService.startActivityAsUser()

// frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
private int startActivityAsUser(IApplicationThread caller, String callingPackage,
        @Nullable String callingFeatureId, Intent intent, String resolvedType,
        IBinder resultTo, String resultWho, int requestCode, int startFlags,
        ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) {
    final SafeActivityOptions opts = SafeActivityOptions.fromBundle(bOptions);
    assertPackageMatchesCallingUid(callingPackage);
    enforceNotIsolatedCaller("startActivityAsUser");

    userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
            Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");

    return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
            .setCaller(caller)
            .setCallingPackage(callingPackage)
            .setCallingFeatureId(callingFeatureId)
            .setResolvedType(resolvedType)
            .setResultTo(resultTo)
            .setResultWho(resultWho)
            .setRequestCode(requestCode)
            .setStartFlags(startFlags)
            .setProfilerInfo(profilerInfo)
            .setActivityOptions(opts)
            .setUserId(userId)
            .execute();
}

这一层的职责很明确:

  1. 做入口安全收口:校验调用包名、隔离进程、目标用户是否合法。
  2. 把原始启动参数整理成内部请求:例如 SafeActivityOptionsuserIdresultTo
  3. 把真正的启动裁决委托给 ActivityStarter

ActivityStarter 是启动 Activity 的控制类,根据设置的参数来决定如何根据 Intent 和 Flags 来启动 Activity,并将 Activity 和 Task 以及 Stack 相关联。它在调用 ActivityStarter 的 execute 方法之前一直有效。

ATMS 在 startActivityAsUser() 中完成调用方与用户合法性校验并封装启动参数,将请求统一收口后委托给 ActivityStarter 做真正的启动决策与执行。

2.2 执行器装配:ActivityStartController 获取 starter,ActivityStarter 创建 ActivityRecord

ActivityStartController 只负责拿到一个可配置的 ActivityStarter

// frameworks/base/services/core/java/com/android/server/wm/ActivityStartController.java
ActivityStarter obtainStarter(Intent intent, String reason) {
    return mFactory.obtain().setIntent(intent).setReason(reason);
}

真正的核心从 ActivityStarter.execute() 进入 executeRequest()

// frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
int execute() {
    ...
    res = executeRequest(mRequest);
    ...
}

private int executeRequest(Request request) {
    ...
    final ActivityRecord r = new ActivityRecord.Builder(mService)
            .setCaller(callerApp)
            .setLaunchedFromPid(callingPid)
            .setLaunchedFromUid(callingUid)
            .setLaunchedFromPackage(callingPackage)
            .setIntent(intent)
            .setResolvedType(resolvedType)
            .setActivityInfo(aInfo)
            .setResultTo(resultRecord)
            .setRequestCode(requestCode)
            .setActivityOptions(checkedOptions)
            .setSourceRecord(sourceRecord)
            .build();

    mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,
            request.voiceInteractor, startFlags, checkedOptions,
            inTask, inTaskFragment, balVerdict, intentGrants, realCallingUid);
    return mLastStartActivityResult;
}

这里最关键的变化是:一次抽象的启动请求,先被系统侧具象化成一个 ActivityRecord

ActivityRecord 还不是客户端里的 Activity 实例,它只是 system_server 里对这次启动的服务端描述:调用来源、目标组件、返回链路、启动参数、所属任务关系,后续都围绕它来决策。

executeRequest() 的核心职责是:把一次 Activity 启动请求从“外部请求”加工成“系统可执行的 ActivityRecord”,期间完成调用方识别、结果回调处理、Intent 解析校验、语音兼容检查、权限检查、后台启动限制、拦截器改写、权限审查、Instant App 改写,最后交给 startActivityUnchecked() 处理 Task 和真正启动。

下一步才是决定它该挂到哪个 Task、要不要复用已有栈、要不要把任务切到前台。

2.3 任务决策:startActivityInner 决定复用还是新建,并把 ActivityRecord 挂进 Task

startActivityUnchecked() 主要负责把流程推进到 startActivityInner();真正的任务决策发生在这里:

// frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord, ...) {
    ...
    result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,
            startFlags, options, inTask, inTaskFragment, balVerdict,
            intentGrants, realCallingUid);
    ...
}

int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord, ...) {
    setInitialState(r, options, inTask, inTaskFragment, startFlags, sourceRecord,
            voiceSession, voiceInteractor, balVerdict.getCode(), realCallingUid);

    computeLaunchingTaskFlags();
    mIntent.setFlags(mLaunchFlags);

    final Task targetTask = reusedTask != null ? reusedTask : computeTargetTask();
    final boolean newTask = targetTask == null;

    if (mTargetRootTask == null) {
        mTargetRootTask = getOrCreateRootTask(mStartActivity, mLaunchFlags, targetTask, mOptions);
    }
    if (newTask) {
        final Task taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
                ? mSourceRecord.getTask() : null;
        setNewTask(taskToAffiliate);
    } else if (mAddingToTask) {
        addOrReparentStartingActivity(targetTask, "adding to task");
    }

    if (!mAvoidMoveToFront && mDoResume) {
        mTargetRootTask.getRootTask().moveToFront("reuseOrNewTask", targetTask);
    }

    if (mDoResume) {
        mRootWindowContainer.resumeFocusedTasksTopActivities(
                mTargetRootTask, mStartActivity, mOptions, mTransientLaunch);
    }
    ...
}

这一段做的不是“真正执行生命周期”,而是先完成 Task 维度的落位

  1. 根据 launchModeflags、来源 Activity、历史任务等因素,判断这次启动是复用旧 Task还是新建 Task
  2. 如果需要新任务,就通过 setNewTask()ActivityRecord 正式挂进去。
  3. 如果是复用路径,就把这次启动和已有任务关系理顺。
  4. 最后在任务层级准备好之后,再调用 resumeFocusedTasksTopActivities() 进入“把谁推到前台”的阶段。

这也是系统侧很重要的一层分工:先把 Activity 放进正确的任务结构里,再决定可见性和恢复。

2.4 恢复顶部 Activity:如果目标进程不存在,就在这里交接到进程启动链路

任务落位之后,RootWindowContainer 会推动顶部 Activity 的恢复:

// frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
boolean resumeFocusedTasksTopActivities(
        Task targetRootTask, ActivityRecord target, ActivityOptions targetOptions,
        boolean deferPause) {
    if (!mTaskSupervisor.readyToResume()) {
        return false;
    }

    if (targetRootTask != null && (targetRootTask.isTopRootTaskInDisplayArea()
            || getTopDisplayFocusedRootTask() == targetRootTask)) {
        result = targetRootTask.resumeTopActivityUncheckedLocked(target, targetOptions,
                deferPause);
    }
    ...
}

Task.resumeTopActivityUncheckedLocked()resumeTopActivityInnerLocked() 主要是中间分发层,真正决定“往客户端 resume,还是先去拉进程”的关键分支,在 TaskFragment.resumeTopActivity()

// frameworks/base/services/core/java/com/android/server/wm/TaskFragment.java
final boolean resumeTopActivity(ActivityRecord prev, ActivityOptions options,
        boolean skipPause) {
    ActivityRecord next = topRunningActivity(true /* focusableOnly */);
    ...
    boolean pausing = !skipPause && taskDisplayArea.pauseBackTasks(next);
    if (mResumedActivity != null) {
        pausing |= startPausing(mTaskSupervisor.mUserLeaving, false, next,
                "resumeTopActivity");
    }
    if (pausing) {
        if (next.attachedToProcess()) {
            next.app.updateProcessInfo(false, true, false, false);
        } else if (!next.isProcessRunning()) {
            final boolean isTop = this == taskDisplayArea.getFocusedRootTask();
            mAtmService.startProcessAsync(next, false /* knownToBeDead */, isTop,
                    isTop ? HostingRecord.HOSTING_TYPE_NEXT_TOP_ACTIVITY
                            : HostingRecord.HOSTING_TYPE_NEXT_ACTIVITY);
        }
        return true;
    }
    ...
    if (next.attachedToProcess()) {
        ...
        final ResumeActivityItem resumeActivityItem = ResumeActivityItem.obtain(...);
        mAtmService.getLifecycleManager().scheduleTransaction(...);
    } else {
        mTaskSupervisor.startSpecificActivity(next, true, true);
    }
    return true;
}

这里可以把恢复路径简化成两个分支:

  • 进程已存在:系统继续准备可见性和状态切换,然后通过 ResumeActivityItem 把恢复事务发给目标进程。
  • 进程不存在:系统不会在这里直接创建进程,而是转到 startSpecificActivity() / startProcessAsync() 做异步交接。

startSpecificActivity() 负责检查目标进程是否已经具备可用的 IApplicationThread

// frameworks/base/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) {
    final WindowProcessController wpc =
            mService.getProcessController(r.processName, r.info.applicationInfo.uid);

    if (wpc != null && wpc.hasThread()) {
        realStartActivityLocked(r, wpc, andResume, checkConfig);
        return;
    }

    final boolean isTop = andResume && r.isTopRunningActivity();
    mService.startProcessAsync(r, knownToBeDead, isTop,
            isTop ? HostingRecord.HOSTING_TYPE_TOP_ACTIVITY
                    : HostingRecord.HOSTING_TYPE_ACTIVITY);
}

startProcessAsync() 只是一个异步交接点

// frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
void startProcessAsync(ActivityRecord activity, boolean knownToBeDead, boolean isTop,
        String hostingType) {
    final Message m = PooledLambda.obtainMessage(ActivityManagerInternal::startProcess,
            mAmInternal, activity.processName, activity.info.applicationInfo, knownToBeDead,
            isTop, hostingType, activity.intent.getComponent());
    mH.sendMessage(m);
}

这段代码有两个信息非常关键:

  1. ATMS 这里没有直接 fork 进程。
  2. 它通过消息把请求异步转交给 ActivityManagerInternal.startProcess(...),保留了清晰的异步交接边界。

后面 AMS 如何处理 startProcess、如何走到 ProcessList / Zygote,那已经是下一篇的主题了。

3. 关键设计点

3.1 统一入口,具体决策后置到 ActivityStarter

ActivityTaskManagerService.startActivityAsUser() 不直接处理复杂的任务复用和生命周期切换,而是先做安全与参数收口,再委托给 ActivityStarter。这种分层把“入口校验”和“启动裁决”拆开了,入口更稳定,执行器更聚焦。

3.2 先建服务端模型,再做前台切换

executeRequest() 先创建 ActivityRecordstartActivityInner() 再决定它挂到哪个 Task。也就是说,系统不是先 resume 再补结构,而是先把任务层级摆正,再推进可见性和生命周期。

3.3 进程启动是异步交接,不在当前决策链里硬做

startProcessAsync() 通过 mH.sendMessage(...) 把请求转给 ActivityManagerInternal.startProcess(...)。本质上这是一次“系统侧裁决链”到“进程创建链”的边界切换。这样做的价值是两点:避免锁耦合,也让任务决策和进程创建各自归位。

4. 高频误区 / QA

4.1 这篇明明叫 AMS 处理阶段,为什么源码大多在 ATMS / WM?

因为 Android 10 之后,Activity 与任务管理能力已经从传统 AMS 里拆分到了 ActivityTaskManagerService 和 WindowManager 相关结构里。系列标题沿用了更通俗的叫法,但实际主链应以源码为准。

4.2 ActivityRecord 创建出来,是不是就等于 Activity 已经启动了?

不是。ActivityRecord 只是 system_server 里的服务端记录,表示“系统已经接受并描述了这次启动”。真正的客户端实例化、onCreate()onResume() 还要看后续是走已有进程恢复,还是先进入进程启动链。

4.3 本阶段会直接把应用进程创建出来吗?

不会。本文里的终点是 startProcessAsync(),它只是把“需要拉起目标进程”这件事异步交给 AMS 本地服务。真正的进程创建、Zygote 通信、ActivityThread 初始化,都属于后续阶段。

5. 总结

AMS 处理阶段的本质,不是“把 Activity 直接跑起来”,而是在 system_server 内部把一次启动请求变成一套可执行的任务与生命周期决策:先校验调用方,再创建 ActivityRecord,再决定 Task 复用或新建,最后推进顶部 Activity 的恢复。

如果目标进程已经存在,后续会进入客户端事务恢复路径;如果目标进程不存在,流程就在 startProcessAsync() 这里切到下一阶段。也就是说,本文的边界就是:ATMS / WM 完成启动裁决,AMS 进程启动链开始接管。