Skip to content

Java调用链

追踪一次冷启动 Activity 从 Activity.startActivity 到 ActivityTaskManagerService、LaunchActivityItem、ActivityThread 主线程和 onCreate 的 Java 调用链,并解释失败、重试、状态所有者与测试边界。

基于android-17.0.0_r1
AndroidJavaActivityBinder源码阅读

Java调用链 ​

本文面向已经会用 rg 查找 Java 符号、知道 Binder 和 Handler 的基本概念,但还不能把应用进程、system_server、AIDL 生成接口和客户端生命周期串成一条因果链的读者。建议先读 ADB架构 了解进程边界,再读 系统控制命令 观察 shell 命令如何进入系统服务。

本文只回答一个问题:应用调用 Activity.startActivity() 后,谁解析 Intent,谁拥有待启动的 ActivityRecord,谁把启动状态变成客户端事务,谁在应用主线程创建 Activity 并调用 onCreate()?失败时,启动前置条件、事务投递失败和 Activity 构造失败分别由谁处理?

这不是 AMS/WMS 类清单,也不讲所有 Activity 启动模式、窗口动画或 PackageManager 解析细节。冷启动是本文的主路径;复用栈顶、onNewIntent() 和完整窗口布局只作为边界。读完后,你应能从一个公开 API 追到跨进程接口、服务端状态、ClientTransaction 消费者和 ActivityThread 的最终回调,并能用固定源码和测试验证这条链。

1. 入口边界 ​

一次启动涉及两个进程和五种主要对象。应用进程里的 Activity 只拥有调用参数和自己的 token;ActivityTaskManagerService(ATMS)在 system_server 拥有任务、ActivityRecord 和启动决策;应用进程的 ActivityThread 最终拥有 ActivityClientRecord 和 Java Activity 实例。

对象所在进程状态所有者消费者生效时机
Intent应用调用方ATMS/解析器Binder 调用前准备
ActivityRecordsystem_serverATMS/WMSActivityStarter、ActivityTaskSupervisor启动决策期间
LaunchActivityItem两侧传输ActivityTaskSupervisor 创建TransactionExecutor客户端事务执行时
ActivityClientRecord应用ActivityThreadperformLaunchActivity主线程处理事务时
Activity 实例应用ActivityThread/应用Instrumentation 与应用代码onCreate() 调用后

“服务端已经返回 START_SUCCESS”不等于“Activity 已经执行 onCreate()”。前者是 ATMS 完成决策并成功投递事务的结果,后者要等客户端主线程消费事务。

2. 调用准备 ​

2.1 API转发 ​

Activity.startActivity() 不直接调用 ATMS。Android 17 仍通过 startActivityForResult() 保留兼容路径,负的 request code 表示调用方不等待结果:

源码文件:frameworks/base/core/java/android/app/Activity.java

java
public void startActivity(Intent intent) {
    this.startActivity(intent, null);
}

public void startActivity(Intent intent, @Nullable Bundle options) {
    getAutofillClientController().onStartActivity(intent, mIntent);
    if (options != null) {
        startActivityForResult(intent, -1, options);
    } else {
        // Keep this call for applications overriding the compatibility path.
        startActivityForResult(intent, -1);
    }
}

真正的边界在 startActivityForResult:调用方把当前 Activity 的 token、应用线程和 request code 交给 Instrumentation。这里的 mMainThread.getApplicationThread() 是应用进程暴露给 system_server 的 IApplicationThread Binder 对象,后续客户端事务正是发给它。

源码文件:frameworks/base/core/java/android/app/Activity.java

java
public void startActivityForResult(@RequiresPermission Intent intent,
        int requestCode, @Nullable Bundle options) {
    if (mParent == null) {
        options = transferSpringboardActivityOptions(options);
        Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity(
                this, mMainThread.getApplicationThread(), mToken, this,
                intent, requestCode, options);
        if (ar != null) {
            mMainThread.sendActivityResult(mToken, mEmbeddedID, requestCode,
                    ar.getResultCode(), ar.getResultData());
        }
        if (requestCode >= 0) mStartedActivity = true;
        cancelInputsAndStartExitTransition(options);
    } else {
        // ... delegate to parent activity
    }
}

2.2 参数准备 ​

Instrumentation.execStartActivity 在跨进程前做三件与主线直接相关的事:注入 referrer,准备 Intent 离开进程,并取得 IActivityTaskManager 代理。它把 Activity 的对象关系压缩成 Binder 能传输的 token、字符串和 Parcelable:

源码文件:frameworks/base/core/java/android/app/Instrumentation.java

java
public ActivityResult execStartActivity(Context who, IBinder contextThread,
        IBinder token, Activity target, Intent intent, int requestCode,
        Bundle options) {
    Objects.requireNonNull(intent);
    IApplicationThread whoThread = (IApplicationThread) contextThread;
    Uri referrer = target != null ? target.onProvideReferrer() : null;
    if (referrer != null) intent.putExtra(Intent.EXTRA_REFERRER, referrer);

    try {
        intent.migrateExtraStreamToClipData(who);
        intent.prepareToLeaveProcess(who);
        int result = ActivityTaskManager.getService().startActivity(
                whoThread, who.getOpPackageName(), who.getAttributionTag(), intent,
                intent.resolveTypeIfNeeded(who.getContentResolver()), token,
                target != null ? target.mEmbeddedID : null, requestCode, 0,
                null, options);
        notifyStartActivityResult(result, options);
        checkStartActivityResult(result, intent);
    } catch (RemoteException e) {
        throw new RuntimeException("Failure from system", e);
    }
    return null;
}

这里的 IActivityTaskManager 是 AIDL 接口,不是 ATMS Java 实例。ActivityTaskManager.getService() 通过 ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE) 得到 Binder,再调用 Stub.asInterface:

源码文件:frameworks/base/core/java/android/app/ActivityTaskManager.java

java
private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton =
        new Singleton<IActivityTaskManager>() {
    @Override
    protected IActivityTaskManager create() {
        final IBinder b = ServiceManager.getService(
                Context.ACTIVITY_TASK_SERVICE);
        return IActivityTaskManager.Stub.asInterface(b);
    }
};

public static IActivityTaskManager getService() {
    return IActivityTaskManagerSingleton.get();
}

Singleton 只缓存客户端接口对象;它不拥有 ActivityRecord,也不意味着每次启动都重新查 ServiceManager。阅读 Java 框架代码时,先区分“接口缓存 owner”和“业务状态 owner”,可以避免把 ActivityTaskManager 当成真正的启动状态机。

3. 服务接收 ​

3.1 AIDL入口 ​

AIDL 的公开契约只保留启动方法的参数形状:

源码文件:frameworks/base/core/java/android/app/IActivityTaskManager.aidl

java
interface IActivityTaskManager {
    int startActivity(in IApplicationThread caller,
            in String callingPackage, in String callingFeatureId,
            in Intent intent, in String resolvedType, in IBinder resultTo,
            in String resultWho, int requestCode, int flags,
            in ProfilerInfo profilerInfo, in Bundle options);
    // ... other task operations
}

生成的 Stub.onTransact 负责 Parcel 解包并调用实现类;生成代码不应作为手写源码主线反复展开。固定阅读路径是 AIDL 声明 → ActivityTaskManagerService.startActivity,中间生成物只用于确认参数和同步返回契约。

3.2 服务状态 ​

ATMS 的实现先把普通入口转为带 user 的入口,再将调用信息交给 ActivityStartController。这一层的 owner 是 system_server:它读取 Binder calling uid、校验包和隔离进程,并创建可配置的 ActivityStarter。

源码文件:frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java

java
@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
        String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
        String resultWho, int requestCode, int startFlags,
        ProfilerInfo profilerInfo, Bundle bOptions) {
    return startActivityAsUser(caller, callingPackage, callingFeatureId, intent,
            resolvedType, resultTo, resultWho, requestCode, startFlags,
            profilerInfo, bOptions, UserHandle.getCallingUserId());
}

深入的 startActivityAsUser 会读取 Binder.getCallingPid/Uid,构造 SafeActivityOptions,校验 caller,最后把字段逐项写入 starter:

源码文件:frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java

java
private int startActivityAsUser(IApplicationThread caller, String callingPackage,
        String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
        String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
        Bundle bOptions, int userId, boolean validateIncomingUser) {
    final int callingPid = Binder.getCallingPid();
    final int callingUid = Binder.getCallingUid();
    final SafeActivityOptions opts = SafeActivityOptions.fromBundle(
            bOptions, callingPid, callingUid);
    assertPackageMatchesCallingUid(callingPackage);
    enforceNotIsolatedCaller("startActivityAsUser");
    userId = getActivityStartController().checkTargetUser(userId,
            validateIncomingUser, callingPid, callingUid,
            "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();
}

3.3 启动决策 ​

ActivityStartController.obtainStarter 返回的是一次请求专用的 builder-like 对象。它不是长期状态 owner;execute() 结束后,controller 会回收 starter。长期可观察状态在 ActivityRecord、Task 和 WindowProcessController 中。

源码文件:frameworks/base/services/core/java/com/android/server/wm/ActivityStartController.java

java
ActivityStarter obtainStarter(Intent intent, String reason) {
    return mFactory.obtain().setIntent(intent).setReason(reason);
}

void onExecutionComplete(ActivityStarter starter) {
    if (mLastStarter == null) mLastStarter = mFactory.obtain();
    mLastStarter.set(starter);
    mFactory.recycle(starter);
}

ActivityStarter.execute() 首先拒绝带文件描述符的 Intent,读取全局锁保护的 caller,并在没有预解析结果时调用 mRequest.resolveActivity。这就是“启动前置条件”与“真正创建客户端事务”之间的边界:

源码文件:frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java

java
int execute() {
    try {
        onExecutionStarted();
        if (mRequest.intent != null) {
            if (mRequest.intent.hasFileDescriptors()) {
                throw new IllegalArgumentException(
                        "File descriptors passed in Intent");
            }
            mRequest.intent.removeExtendedFlags(
                    Intent.EXTENDED_FLAG_FILTER_MISMATCH);
        }
        synchronized (mService.mGlobalLock) {
            caller = ActivityRecord.forTokenLocked(mRequest.resultTo);
            callingUid = Binder.getCallingUid();
        }
        if (mRequest.activityInfo == null) {
            mRequest.resolveActivity(mSupervisor);
        }
        // ... permissions, launch mode and task decisions
    } finally {
        onExecutionComplete();
    }
}

解析失败不会进入客户端生命周期。源码明确把“Intent 没有匹配组件”和“指定类不存在”分别映射为 START_INTENT_NOT_RESOLVED 与 START_CLASS_NOT_FOUND,之后由调用方 checkStartActivityResult 转为异常或兼容结果。

4. 服务决策 ​

4.1 结果状态 ​

ActivityStarter 的内部结果码不是“Activity 已显示”的布尔值。它可能表示已交付到栈顶、把已有 Task 拉到前台、权限拒绝或解析失败。本文只沿冷启动成功路径继续;所有结果都要先经过 Instrumentation.checkStartActivityResult,避免把服务端中间状态误当作客户端回调。

源码文件:frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java

java
if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
    err = ActivityManager.START_INTENT_NOT_RESOLVED;
}
if (err == ActivityManager.START_SUCCESS && aInfo == null) {
    err = ActivityManager.START_CLASS_NOT_FOUND;
}

服务端只返回整数结果;应用侧还要把这个结果转换成公开异常或兼容的非致命状态。

源码文件:frameworks/base/core/java/android/app/Instrumentation.java

java
public static void checkStartActivityResult(int res, Object intent) {
    if (!ActivityManager.isStartResultFatalError(res)) {
        return;
    }
    switch (res) {
        case ActivityManager.START_INTENT_NOT_RESOLVED:
        case ActivityManager.START_CLASS_NOT_FOUND:
            throw new ActivityNotFoundException(
                    "No Activity found to handle " + intent);
        case ActivityManager.START_PERMISSION_DENIED:
            throw new SecurityException(
                    "Not allowed to start activity " + intent);
        // ... other fatal result mappings
        default:
            throw new AndroidRuntimeException(
                    "Unknown error code " + res + " when starting " + intent);
    }
}

调用方消费的是外部异常/返回语义,ATMS 消费的是内部状态码;两者不应混写。特别是 START_SUCCESS 只说明服务端决策成功,并不证明客户端对象已创建。

4.2 进程归属 ​

当目标进程已经存在或刚刚准备好,ActivityTaskSupervisor.realStartActivityLocked 把 ActivityRecord 与 WindowProcessController 绑定,并构造客户端要执行的两个事务项:启动项和最终生命周期项。

源码文件:frameworks/base/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java

java
final LaunchActivityItem launchActivityItem = new LaunchActivityItem(
        r.token, r.intent, System.identityHashCode(r), r.info,
        procConfig, overrideConfig, deviceId,
        r.getFilteredReferrer(r.launchedFromPackage), task.voiceInteractor,
        proc.getReportedProcState(), r.getSavedState(), persistentState,
        results, newIntents, r.takeSceneTransitionInfo(), isTransitionForward,
        proc.createProfilerInfoIfNeeded(), r.assistToken, activityClientController,
        r.shareableActivityToken, r.getLaunchedFromBubble(), fragmentToken,
        r.initialCallerInfoAccessToken, activityWindowInfo, r.getDisplayId());

final ActivityLifecycleItem lifecycleItem = andResume
        ? new ResumeActivityItem(r.token, isTransitionForward,
                r.shouldSendCompatFakeFocus())
        : r.isVisibleRequested() ? new PauseActivityItem(r.token)
                : new StopActivityItem(r.token);

LaunchActivityItem 携带的是创建 Activity 所需的快照:Intent、ActivityInfo、配置、保存状态和 token;ResumeActivityItem 决定创建后是否继续到 resumed。服务端在这里准备输入,客户端在之后消费输入。

5. 客户端事务 ​

5.1 投递时机 ​

ClientLifecycleManager 会按 IApplicationThread 聚合待发送的 ClientTransaction。冷启动路径显式传入 shouldDispatchImmediately = true,因为服务端需要立刻知道目标进程是否已经死亡;普通更新可能等待窗口布局结束再批量发送。

源码文件:frameworks/base/services/core/java/com/android/server/wm/ClientLifecycleManager.java

java
boolean scheduleTransactionItems(@NonNull IApplicationThread client,
        boolean shouldDispatchImmediately,
        @NonNull ClientTransactionItem... items) {
    final ClientTransaction transaction = getOrCreatePendingTransaction(client);
    for (int i = 0; i < items.length; i++) {
        transaction.addTransactionItem(items[i]);
    }
    return onClientTransactionItemScheduled(transaction,
            shouldDispatchImmediately);
}

private boolean onClientTransactionItemScheduled(
        ClientTransaction transaction, boolean shouldDispatchImmediately) {
    if (shouldDispatchImmediately || shouldDispatchPendingTransactionsImmediately()) {
        mPendingTransactions.remove(transaction.getClient().asBinder());
        return scheduleTransaction(transaction);
    }
    return true;
}

ClientTransaction.schedule() 调用 mClient.scheduleTransaction(this)。这一次 Binder 调用的消费者是应用进程的 ActivityThread.ApplicationThread,而不是 Activity 实例:

源码文件:frameworks/base/core/java/android/app/servertransaction/ClientTransaction.java

java
public RemoteException schedule() {
    try {
        mClient.scheduleTransaction(this);
        return null;
    } catch (RemoteException e) {
        return e;
    }
}

5.2 主线程入队 ​

应用侧的 Binder 回调只把事务交给 ClientTransactionHandler.scheduleTransaction,后者先执行每个 item 的 preExecute,再发送 H.EXECUTE_TRANSACTION。这一步解释了“Binder 线程收到请求”和“Activity.onCreate 在主线程运行”之间的断点。

源码文件:frameworks/base/core/java/android/app/ActivityThread.java

java
@Override
public void scheduleTransaction(ClientTransaction transaction)
        throws RemoteException {
    ActivityThread.this.scheduleTransaction(transaction);
}

Binder 回调到达 ApplicationThread 后,调用方向从 Binder stub 转回 ClientTransactionHandler 的调度方法;真正的消息入队发生在下一段代码。

源码文件:frameworks/base/core/java/android/app/ClientTransactionHandler.java

java
void scheduleTransaction(ClientTransaction transaction) {
    transaction.preExecute(this);
    sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
}

ActivityThread.H 收到消息后才调用 TransactionExecutor:

源码文件:frameworks/base/core/java/android/app/ActivityThread.java

java
case EXECUTE_TRANSACTION:
    final ClientTransaction transaction = (ClientTransaction) msg.obj;
    final ClientTransactionListenerController controller =
            ClientTransactionListenerController.getInstance();
    controller.onClientTransactionStarted();
    try {
        mTransactionExecutor.execute(transaction);
    } finally {
        controller.onClientTransactionFinished();
    }
    break;

5.3 事务解析 ​

TransactionExecutor 按 item 顺序执行,并根据 Activity 当前状态补齐生命周期路径。冷启动时 token 尚未对应一个已创建的 ActivityClientRecord,LaunchActivityItem 是能够创建它的特殊 item;后续 ResumeActivityItem 才能继续状态转换。

源码文件:frameworks/base/core/java/android/app/servertransaction/TransactionExecutor.java

java
public void execute(@NonNull ClientTransaction transaction) {
    Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER,
            "clientTransactionExecuted");
    try {
        executeTransactionItems(transaction);
    } catch (Exception e) {
        Slog.e(TAG, "Failed to execute the transaction: "
                + transactionToString(transaction, mTransactionHandler));
        throw e;
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
    }
    mPendingActions.clear();
}

public void executeTransactionItems(@NonNull ClientTransaction transaction) {
    final List<ClientTransactionItem> items = transaction.getTransactionItems();
    for (int i = 0; i < items.size(); i++) {
        final ClientTransactionItem item = items.get(i);
        if (item.isActivityLifecycleItem()) {
            executeLifecycleItem(transaction, (ActivityLifecycleItem) item);
        } else {
            executeNonLifecycleItem(transaction, item,
                    shouldExcludeLastLifecycleState(items, i));
        }
    }
}

这段代码保留了 Android 17 的真实索引和状态排除判断;后续 executeNonLifecycleItem 还会处理“先 destroy 后 launch”的取消容器。阅读生成/调度框架时,必须继续跟进这个消费者,而不能停在 ClientTransaction 的字段列表。

6. 实例创建 ​

6.1 启动项 ​

LaunchActivityItem.execute() 只负责把传输字段组装成 ActivityClientRecord,然后调用 ClientTransactionHandler.handleLaunchActivity。它不直接反射创建类,也不调用 onCreate()。

源码文件:frameworks/base/core/java/android/app/servertransaction/LaunchActivityItem.java

java
@Override
public void execute(@NonNull ClientTransactionHandler client,
        @NonNull PendingTransactionActions pendingActions) {
    Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
    final ActivityClientRecord r = new ActivityClientRecord(
            mActivityToken, mIntent, mIdent, mInfo, mOverrideConfig,
            mReferrer, mVoiceInteractor, mState, mPersistentState,
            mPendingResults, mPendingNewIntents, mSceneTransitionInfo,
            mIsForward, mProfilerInfo, client, mAssistToken,
            mShareableActivityToken, mLaunchedFromBubble,
            mTaskFragmentToken, mInitialCallerInfoAccessToken,
            mActivityWindowInfo, mDisplayId);
    client.handleLaunchActivity(r, pendingActions, mDeviceId, null);
    Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}

6.2 反射实例 ​

ActivityThread.handleLaunchActivity 先处理配置、渲染和窗口环境,再调用 performLaunchActivity。后者从 ActivityInfo 取得类名和 ClassLoader,通过 Instrumentation.newActivity 创建实例;类加载失败会进入 onException,默认转成启动失败。

源码文件:frameworks/base/core/java/android/app/ActivityThread.java

java
public Activity handleLaunchActivity(ActivityClientRecord r,
        PendingTransactionActions pendingActions, int deviceId,
        Intent customIntent) {
    unscheduleGcIdler();
    mSomeActivitiesChanged = true;
    applyPendingApplicationInfoChanges(r.activityInfo.packageName);
    mConfigurationController.handleConfigurationChanged(null, null);
    WindowManagerGlobal.initialize();

    final Activity a = performLaunchActivity(r, customIntent);
    if (a != null) {
        r.createdConfig = new Configuration(
                mConfigurationController.getConfiguration());
        if (!r.activity.mFinished && pendingActions != null) {
            pendingActions.setOldState(r.state);
            pendingActions.setRestoreInstanceState(true);
            pendingActions.setCallOnPostCreate(true);
        }
    } else {
        ActivityClient.getInstance().finishActivity(r.token,
                Activity.RESULT_CANCELED, null,
                Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
    }
    return a;
}

6.3 生命周期回调 ​

performLaunchActivity 创建实例后把它放进 mActivities,调用 attach 建立 Context、token、Instrumentation 和 Application 关系,最后才由 Instrumentation.callActivityOnCreate 进入应用覆写的 onCreate:

源码文件:frameworks/base/core/java/android/app/ActivityThread.java

java
activity = mInstrumentation.newActivity(
        cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess(isProtectedComponent(r.activityInfo),
        activityBaseContext.getAttributionSource());

Application app = r.packageInfo.makeApplicationInner(false, mInstrumentation);
synchronized (mResourcesManager) {
    mActivities.put(r.token, r);
}

activityBaseContext.setOuterContext(activity);
activity.attach(activityBaseContext, this, getInstrumentation(), r.token,
        r.ident, app, r.intent, r.activityInfo, title, r.parent,
        r.embeddedID, r.lastNonConfigurationInstances, config,
        r.referrer, r.voiceInteractor, window,
        r.activityConfigCallback, r.assistToken,
        r.shareableActivityToken, r.initialCallerInfoAccessToken);
r.activity = activity;
if (r.isPersistable()) {
    mInstrumentation.callActivityOnCreate(
            activity, r.state, r.persistentState);
} else {
    mInstrumentation.callActivityOnCreate(activity, r.state);
}
if (!activity.mCalled) {
    throw new SuperNotCalledException(
            "Activity " + r.intent.getComponent().toShortString()
                    + " did not call through to super.onCreate()");
}
r.setState(ON_CREATE);

这里的生效顺序很具体:先把 Activity 放入 mActivities,再调用 onCreate(),使回调期间的 ActivityThread#getActivity(token) 能找到当前实例;onCreate 正常返回后,客户端记录状态才变为 ON_CREATE。这比“Activity 生命周期由 Handler 驱动”更精确:Handler 只触发事务消费,状态转换由 TransactionExecutor 和具体 item 共同完成。

7. 异常分流 ​

7.1 启动拒绝 ​

启动失败的第一类发生在 ActivityStarter 仍拥有请求时:无匹配组件、类不存在、权限不足、Intent 带 fd 或后台启动限制都可能在创建 LaunchActivityItem 前结束。此时应用收到结果码映射后的异常,应用进程不会收到启动事务。

7.2 事务失败 ​

第二类发生在服务端已经建立 ActivityRecord,但 scheduleTransactionItems 通过 Binder 投递时遇到 RemoteException。realStartActivityLocked 把它包装成 DeadObjectException 返回;如果这是第一次失败,源码会标记 r.launchFailed、脱离旧进程并抛出异常,让上层重启进程重试;第二次失败则 finishIfPossible("2nd-crash", ...) 结束 Activity。

源码文件:frameworks/base/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java

java
final boolean isSuccessful = mService.getLifecycleManager()
        .scheduleTransactionItems(proc.getThread(), true,
                launchActivityItem, lifecycleItem);
if (!isSuccessful) {
    return new DeadObjectException(
            "Failed to dispatch the ClientTransaction to dead process");
}

// In the caller's retry path:
if (e != null) {
    if (r.launchFailed) {
        Slog.e(TAG, "Second failure launching ...", e);
        proc.appDied("2nd-crash");
        r.finishIfPossible("2nd-crash", false);
        return false;
    }
    r.launchFailed = true;
    r.detachFromProcess();
    throw e;
}

“事务发送失败”不是“Activity 的 onCreate 抛异常”。前者发生在客户端执行之前,后者发生在应用主线程实例化之后;两个 owner、日志和恢复策略都不同。

7.3 客户端失败 ​

第三类发生在 newActivity、attach 或 onCreate。handleLaunchActivity 如果得到 null,会调用 finishActivity 把失败报告回服务端;如果 onCreate 没有调用父类,SuperNotCalledException 直接中止事务。此时 ActivityClientRecord 可能已经暂存于 mActivities,后续清理由 ActivityThread 和服务端失败路径共同完成,不能只看 Activity 构造函数。

8. 测试路径 ​

8.1 服务决策 ​

services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java 的 testStartActivityPreconditions 用 bitmask 组合前置条件,断言内部错误码映射:没有 caller 应为权限拒绝,没有组件应为未解析,没有 ActivityInfo 应为类不存在,禁止启动应为 START_ABORTED。它的 arrange/action/assert 是:构造 mock ActivityStarter 环境;设置 Intent、caller、ActivityInfo 和权限前置;调用 execute();比较 getExternalResult(expectedResult)。

源码文件:frameworks/base/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java

java
verifyStartActivityPreconditions(PRECONDITION_NO_CALLER_APP,
        START_PERMISSION_DENIED);
verifyStartActivityPreconditions(PRECONDITION_NO_INTENT_COMPONENT,
        START_INTENT_NOT_RESOLVED);
verifyStartActivityPreconditions(PRECONDITION_NO_ACTIVITY_INFO,
        START_CLASS_NOT_FOUND);
verifyStartActivityPreconditions(PRECONDITION_CANNOT_START_ANY_ACTIVITY,
        START_ABORTED);

final int result = starter.setCaller(caller).setIntent(intent)
        .setActivityInfo(aInfo).setResultTo(resultTo)
        .setRequestCode(requestCode).setReason(name.getMethodName())
        .execute();
assertEquals(ActivityStarter.getExternalResult(expectedResult), result);

它证明服务端前置条件和结果映射,不证明真实 PackageManager、Binder 生成代码或设备上的进程启动。

8.2 生命周期解析 ​

FrameworksCoreTests:TransactionExecutorTests 验证状态路径。测试从 PRE_ON_CREATE 到 ON_RESUME 断言路径为 ON_CREATE → ON_START → ON_RESUME,从 ON_RESUME 到 ON_DESTROY 断言经过 ON_PAUSE → ON_STOP → ON_DESTROY。这里检查的是 TransactionExecutorHelper 的状态规划,不涉及每个 Activity 回调都能成功执行。

源码文件:frameworks/base/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java

java
@Test
public void testLifecycleFromPreOnCreate() {
    mClientRecord.setState(PRE_ON_CREATE);
    assertArrayEquals(new int[] {ON_CREATE}, path(ON_CREATE));
    assertArrayEquals(new int[] {ON_CREATE, ON_START}, path(ON_START));
    assertArrayEquals(new int[] {ON_CREATE, ON_START, ON_RESUME},
            path(ON_RESUME));
}

@Test(expected = IllegalArgumentException.class)
public void testLifecycleUndefinedFinishState() {
    mClientRecord.setState(PRE_ON_CREATE);
    path(UNDEFINED);
}

另一个测试 testDoNotLaunchDestroyedActivity 将 destroy 事务先放入待销毁容器,再执行尚未消费的 launch 事务,断言 LaunchActivityItem.execute() 不被调用,随后销毁事务清空容器。这是取消/竞态边界的证据:客户端收到“先销毁、后启动”的排队顺序时,启动项会被跳过,而不是无条件创建 Activity。

9. 阅读复现 ​

固定源码树中可以用下面的命令重走入口、服务端、客户端和测试,而不依赖记忆:

bash
rg -n 'startActivity\(|execStartActivity|IActivityTaskManagerSingleton' \
  frameworks/base/core/java/android/app
rg -n 'startActivity\(|obtainStarter|int execute\(\)' \
  frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java \
  frameworks/base/services/core/java/com/android/server/wm/ActivityStartController.java \
  frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
rg -n 'realStartActivityLocked|LaunchActivityItem|scheduleTransactionItems' \
  frameworks/base/services/core/java/com/android/server/wm
rg -n 'EXECUTE_TRANSACTION|handleLaunchActivity|performLaunchActivity' \
  frameworks/base/core/java/android/app

如果有设备,再用一个已安装组件和一个不存在组件对照:

bash
adb shell am start -W -n com.android.settings/.Settings
adb shell am start -W -n com.example.__missing__/.MissingActivity

阅读输出时不要只看“成功/失败”。把现象映射回 owner:不存在组件应停在 ActivityStarter 的解析分支;应用启动后立刻崩溃应查 performLaunchActivity 和 onCreate;反复出现进程死亡重试应查 scheduleTransactionItems、launchFailed 和 ActivityTaskSupervisor。最后尝试不看本文复述:API 参数如何到达 ATMS,ActivityRecord 如何变成 LaunchActivityItem,Binder 回调为何只入队,谁在主线程创建实例,哪一类失败会重试。能完成这段复述,才说明你学会的是源码路径而不是类名。

10. 边界收束 ​

本文沿着 Android 17 冷启动 Activity 的 Java 用户态主线讲解:Activity API 准备请求,Instrumentation 调用 AIDL 服务,ATMS/ActivityStarter 持有决策状态,ActivityTaskSupervisor 创建并投递 ClientTransaction,应用 ActivityThread 在主线程消费 LaunchActivityItem 并调用 onCreate()。

本文没有证明窗口 surface 已经完成布局,也没有覆盖已有 Activity 的 onNewIntent、完整 ResumeActivityItem 实现、PackageManager 的全部 Intent 解析规则或设备厂商修改。下一次阅读类似 Java 框架链路时,仍应按“入口参数 → 跨进程接口 → 服务状态 owner → 客户端事务 → 最终消费者 → 失败清理”的顺序逐段核对源码。