目录

再来看 Activity 启动流程

很久之前的一篇 Activity 启动流程 当时刚毕业,有很多错误和没有理解,今天重新写一篇比较完整的,源码基于 Android 9.0

1.概览

startActivity 流程,主要涉及 APP 进程和 ActivityManagerService(简写为 AMS,system_process 为其所在进程名) 之间的 IPC 通信

我一直带着几个问题在看代码

问题1
ActivityA.startActivityB,其生命周期为 A.onPause -> B.onCreate -> B.onStart -> B.onResume,具体流程是怎样的,onPause 如何被执行的?

问题2
当有多个 Activity 可以处理 Intent 时,选择弹窗如何出现的?

问题3
进程不存在的情况下,如何创建进程,并且如何再次继续执行 startActivity 流程的?

问题4
onNewIntent 何时被执行,启动模式如何处理的?

问题5
到底什么是 ActivityStack,什么是 TaskRecord,什么又是 ActivityRecord?

极简易 IPC 流程图(省略了 PMS 和 WMS 等各种相关流程)

/img/in-post/startActivity.jpg

2.流程分析

ActivityA.startActivityB 流程分析

2.1 ActivityA.startActivity 的一些逻辑

当 startActivity 被调用后,层层逻辑会去获取 AMS 代理对象,然后执行一次 IPC 调用,进入 AMS 所在进程。
调用栈如下:

execStartActivity:1666, Instrumentation (android.app)
startActivityForResult:4586, Activity (android.app)
startActivityForResult:54, BaseFragmentActivityApi16 (android.support.v4.app)
startActivityForResult:65, FragmentActivity (android.support.v4.app)
startActivityForResult:4544, Activity (android.app)
startActivityForResult:711, FragmentActivity (android.support.v4.app)
startActivity:4905, Activity (android.app)
startActivity:4873, Activity (android.app)
onResult:2337, AccountManager$AmsTask$Response (android.accounts)
onTransact:60, IAccountManagerResponse$Stub (android.accounts)
execTransact:731, Binder (android.os)

核心代码 Instrumentation.execStartActivity

ActivityManager.getService().startActivity(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null ? target.mEmbeddedID : null, requestCode, 0, null, options);

此处执行在 ActivityB 所在进程,最后通过取 AMS Binder 代理对象,实现跨进程调用

2.2 ActivityB 即将启动的各种逻辑

当 startActivity 跨进程调用到了 AMS 中后,AMS 处理了大量逻辑并且存在大量容错和各种复杂情况,我至今没法完全理解一些方法的作用,但是主线是很清晰的。

进入 AMS 之后的前半部分调用栈如下,为什么说是前半部分呢?因为 ActivityA.onPause 执行还要通过 IPC 回到 APP 进程。

前部分调用栈:

resumeTopActivityInnerLocked:2448, ActivityStack (com.android.server.am) 
resumeTopActivityUncheckedLocked:2302, ActivityStack (com.android.server.am)
resumeFocusedStackTopActivityLocked:2229, ActivityStackSupervisor (com.android.server.am)
startActivityUnchecked:1466, ActivityStarter (com.android.server.am)
startActivity:1200, ActivityStarter (com.android.server.am)
startActivity:868, ActivityStarter (com.android.server.am)
startActivity:544, ActivityStarter (com.android.server.am)
startActivityMayWait:1099, ActivityStarter (com.android.server.am)
execute:486, ActivityStarter (com.android.server.am)
startActivityAsUser:5120, ActivityManagerService (com.android.server.am)
startActivityAsUser:5094, ActivityManagerService (com.android.server.am)
startActivity:5085, ActivityManagerService (com.android.server.am)
onTransact$startActivity$:10084, IActivityManager$Stub (android.app)
onTransact:122, IActivityManager$Stub (android.app)
onTransact:3291, ActivityManagerService (com.android.server.am)
execTransact:731, Binder (android.os)

其中 ActivityStarter.startActivityMayWait 可以解释 问题2

其关键代码如下:

ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId, 0 /* matchFlags */, computeResolveFilterUid(callingUid, realCallingUid, mRequest.filterCallingUid));
ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);

mSupervisor.resolveIntent 中会调用

mService.getPackageManagerInternalLocked().resolveIntent(intent, resolvedType, modifiedFlags, userId, true, filterCallingUid);

这里又是通过 Binder IPC 进入 PMS 中处理 intent,debug 发现 resolveIntent 方法已经解析出了符合要求的 Activity,如果 >= 2,那么会变为 ResolverActivity,这个 Activity 便是选择应用的弹窗 Activity

resumeTopActivityInnerLocked 方法在存在 resumeActivity 时会触发 onPause 的回调,如果没有则进入 startSpecificActivityLocked 走后续流程

2.2.1 ActivityA onPause 的执行

前半部的调用栈最后一个方法就是 resumeTopActivityInnerLocked,在这个方法中有一行代码如下:

if (mResumedActivity != null) {
    pausing |= startPausingLocked(userLeaving, false, next, false);
}

startPausingLocked 后续会通过 Binder IPC 调用回到 APP 进程,关键代码如下

mService.getLifecycleManager().scheduleTransaction(prev.app.thread, prev.appToken, PauseActivityItem.obtain(prev.finishing, userLeaving, prev.configChangeFlags, pauseImmediately));

scheduleTransaction 最终会进入 ClientTransaction.scheduleTransaction,里面的 mClient 即 ApplicationThread(ApplicationThread 是跟随 APP 创建而出现的) 的 Binder 代理对象,这里还是通过 Binder IPC 调用到 APP 进程中。

而到了 APP 进程中就是 ActivityThread 通过 Handler 处理各种 Message,最终执行到 TransactionExecutor.execute!

这里看代码注意 ActivityThread extends ClientTransactionHandler 就好,找不到的 transaction 相关方法,都在这个父类中

public void execute(ClientTransaction transaction) {
    final IBinder token = transaction.getActivityToken();
    log("Start resolving transaction for client: " + mTransactionHandler + ", token: " + token);

    executeCallbacks(transaction);

    executeLifecycleState(transaction);
    mPendingActions.clear();
    log("End resolving transaction");
}

execute 方法中的 executeLifecycleState 方法很关键,代码如下:

/** Transition to the final state if requested by the transaction. */
private void executeLifecycleState(ClientTransaction transaction) {
    final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();
    if (lifecycleItem == null) {
        // No lifecycle request, return early.
        return;
    }
    log("Resolving lifecycle state: " + lifecycleItem);

    final IBinder token = transaction.getActivityToken();
    final ActivityClientRecord r = mTransactionHandler.getActivityClient(token);

    if (r == null) {
        // Ignore requests for non-existent client records for now.
        return;
    }

    // Cycle to the state right before the final requested state.
    cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */);

    // Execute the final transition with proper parameters.
    lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
    lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
}

lifecycleItem.execute 和 postExecute,基本就包含了 onPause 需要的整个过程。

看一下 PauseActivityItem 的代码:

@Override
public void execute(ClientTransactionHandler client, IBinder token,
        PendingTransactionActions pendingActions) {
    Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
    client.handlePauseActivity(token, mFinished, mUserLeaving, mConfigChanges, pendingActions,
            "PAUSE_ACTIVITY_ITEM");
    Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}

@Override
public void postExecute(ClientTransactionHandler client, IBinder token,
        PendingTransactionActions pendingActions) {
    if (mDontReport) {
        return;
    }
    try {
        // TODO(lifecycler): Use interface callback instead of AMS.
        ActivityManager.getService().activityPaused(token);
    } catch (RemoteException ex) {
        throw ex.rethrowFromSystemServer();
    }
}

execute 中调用了 handlePauseActivity,最终会调用到 Activity.onPause 方法,而 postExecute 中,又会通过 Binder IPC 调用到 AMS 进程,继续执行 Activity 启动的后续流程。

handlePauseActivity 到 Activity.onPause 的调用栈如下:

onPause:1731, Activity (android.app)
onPause:395, FragmentActivity (android.support.v4.app)
performPause:7329, Activity (android.app)
callActivityOnPause:1465, Instrumentation (android.app)
performPauseActivityIfNeeded:4021, ActivityThread (android.app)
performPauseActivity:3986, ActivityThread (android.app)
handlePauseActivity:3938, ActivityThread (android.app)
execute:45, PauseActivityItem (android.app.servertransaction)
executeLifecycleState:145, TransactionExecutor (android.app.servertransaction)
execute:70, TransactionExecutor (android.app.servertransaction)
handleMessage:1808, ActivityThread$H (android.app)
dispatchMessage:106, Handler (android.os)
loop:193, Looper (android.os)
main:6669, ActivityThread (android.app)
invoke:-1, Method (java.lang.reflect)
run:493, RuntimeInit$MethodAndArgsCaller (com.android.internal.os)
main:858, ZygoteInit (com.android.internal.os)

回调到 AMS 中的后续流程调用栈如下:

startSpecificActivityLocked:1688, ActivityStackSupervisor (com.android.server.am)
resumeTopActivityInnerLocked:2764, ActivityStack (com.android.server.am)
resumeTopActivityUncheckedLocked:2302, ActivityStack (com.android.server.am)
resumeFocusedStackTopActivityLocked:2229, ActivityStackSupervisor (com.android.server.am)
completePauseLocked:1606, ActivityStack (com.android.server.am)
activityPausedLocked:1530, ActivityStack (com.android.server.am)
activityPaused:8161, ActivityManagerService (com.android.server.am)
onTransact:224, IActivityManager$Stub (android.app)
onTransact:3291, ActivityManagerService (com.android.server.am)
execTransact:731, Binder (android.os)

所以,最终又会回到 startSpecificActivityLocked,这个关键的方法

上述的 ActivityA.startActivity -> AcitivtyA.onPause 解释了 问题1

2.2.2 startSpecificActivityLocked

无论需不需要 onPause,最终都会执行到 startSpecificActivityLocked。这个方法中判断了进程是否已经存在,在整个流程中,经常有 app.thread 字样出现,app.thread == ApplicationThread 是个 Binder 对象。它跟随着 APP 进程的创建而创建并且传递给 AMS 进程的。

startSpecificActivityLocked 简洁的代码如下:

if (app != null && app.thread != null) {
    realStartActivityLocked(r, app, andResume, checkConfig);
    return;
}
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0, "activity", r.intent.getComponent(), false, false, true);

所以,如果进程存在,则进入 realStartActivityLocked 走下一步流程。如果进程不存在则 startProcessLocked,启动一个 APP 进程。

启动进程的流程其实很复杂,也包括了 socket 的跨进程调用,fork 进程,反射启动 ActivityThread.main 方法等等

ActivityThread.main 方法首先创建了 ActivityThread 对象,与此同时

final ApplicationThread mAppThread = new ApplicationThread();

作为成员变量的 ApplicationThread 也会被初始化,之后调用到 ActivityThread.attach 方法,关键代码如下:

final IActivityManager mgr = ActivityManager.getService();
try {
    mgr.attachApplication(mAppThread, startSeq);
} catch (RemoteException ex) {
    throw ex.rethrowFromSystemServer();
}

所以,又通过 Binder IPC 回到 AMS 中,这就是 ApplicationThread 的源头。

AMS.attachApplication 的后续调用栈如下:

realStartActivityLocked:1393, ActivityStackSupervisor (com.android.server.am)
attachApplicationLocked:989, ActivityStackSupervisor (com.android.server.am)
attachApplicationLocked:7872, ActivityManagerService (com.android.server.am)
attachApplication:7940, ActivityManagerService (com.android.server.am)
onTransact:198, IActivityManager$Stub (android.app)
onTransact:3291, ActivityManagerService (com.android.server.am)
execTransact:731, Binder (android.os)

realStartActivityLocked 这个方法再次出现,所以一切又回到了启动 Activity 的流程中。

这里的整个流程解释了 问题3

所以无论是否需要创建进程,我们最终都会进入 realStartActivityLocked 方法中

2.2.3 realStartActivityLocked

realStartActivityLocked 核心代码如下:

// Create activity launch transaction.
final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread,
        r.appToken);
clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
        System.identityHashCode(r), r.info,
        // TODO: Have this take the merged configuration instead of separate global
        // and override configs.
        mergedConfiguration.getGlobalConfiguration(),
        mergedConfiguration.getOverrideConfiguration(), r.compat,
        r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
        r.persistentState, results, newIntents, mService.isNextTransitionForward(),
        profilerInfo));

// Set desired final state.
final ActivityLifecycleItem lifecycleItem;
if (andResume) {
    lifecycleItem = ResumeActivityItem.obtain(mService.isNextTransitionForward());
} else {
    lifecycleItem = PauseActivityItem.obtain();
}
clientTransaction.setLifecycleStateRequest(lifecycleItem);

// Schedule transaction.
mService.getLifecycleManager().scheduleTransaction(clientTransaction);

这里和 2.2.1 整个流程很相近,都是通过 scheduleTransaction,然后进入 APP 所在进程,通过 ActivityThread Handler 执行相应的生命周期相关的 ActivityItem 方法。

唯一不同的是,这里是 clientTransaction.addCallback(LaunchActivityItem),然后 clientTransaction.setLifecycleStateRequest(ResumeActivityItem)

这个不同点的处理过程的关键代码如下:

public void preExecute(android.app.ClientTransactionHandler clientTransactionHandler) {
    if (mActivityCallbacks != null) {
        final int size = mActivityCallbacks.size();
        for (int i = 0; i < size; ++i) {
            mActivityCallbacks.get(i).preExecute(clientTransactionHandler, mActivityToken);
        }
    }
    if (mLifecycleStateRequest != null) {
        mLifecycleStateRequest.preExecute(clientTransactionHandler, mActivityToken);
    }
}

所以,preExecute 时就会处理 callback 相关的代码,preExecute 在 ActivityThread(ClientTransactionHandler).excuteTransaction 方法中被执行,代码如下:

public void executeTransaction(ClientTransaction transaction) {
    transaction.preExecute(this);
    getTransactionExecutor().execute(transaction);
    transaction.recycle();
}

所以我们会先执行 LaunchActivityItem 然后执行 ResumeActivityItem

2.3 ActivityB 的 onCreate onStart onResume

前面知道了,我们会先后执行 LaunchActivityItem 和 ResumeActivityItem。LaunchActivityItem 会调用到 handleLaunchActivity,之后会调用到 Activity.onCreate 方法,这其中支线流程其实也很复杂,包含了 Activity.attach 方法和 WMS 的一些关联。

ResumeActivityItem 会调用到 handleResumeActivity,之后会调用到 onResume 方法。

onStart 方法呢?

这里注意到一个方法 cycleToPath,在 TransactionExecutor 中执行 executeLifecycleState 时,总会先调用这个方法。此方法根据生命周期的值,判断当前要执行到哪个生命周期。

cycleToPath 代码如下:

private void cycleToPath(ActivityClientRecord r, int finish,
            boolean excludeLastState) {
    final int start = r.getLifecycleState();
    log("Cycle from: " + start + " to: " + finish + " excludeLastState:" + excludeLastState);
    final IntArray path = mHelper.getLifecyclePath(start, finish, excludeLastState);
    performLifecycleSequence(r, path);
}

在执行 ResumeActivityItem 时,生命周期在 onCreate 和 onResume 之中,但是在定义中,还存在 onStart。这个方法会添加 onStart 和 onReume 生命周期,但是又因为参数原因,删掉了 onResume,所以此时只有 onStart 即 getLifecyclePath 会返回 onStart。然后会执行 performLifecycleSequence 方法,然后会执行到 mTransactionHandler.handleStartActivity 方法中,最终调用到 onStart 方法。

在 cycleToPath 此方法已经执行了之后,才会走到 execute 方法,执行 ResumeActivityItem 相关的方法,最终通过 handleResumeActivity 也会调用到 onResume 方法。

所以其实 AMS 不关心 onStart 这个生命周期吧

至此重要的流程基本结束了

这其中也解释了为什么不要在 onPause 中做耗时的操作,因为后一个 Activity 的启动需要等待前一个 onPause 流程的结束

2.4 ActivityA 的 onStop onDestroy 方法

2.4.1 onStop 的执行

在之前 ActivityThread 中执行 handleResumeActivity 时,有一行代码如下:

Looper.myQueue().addIdleHandler(new Idler());

// Idler 中
try {
    am.activityIdle(a.token, a.createdConfig, stopProfiling);
    a.createdConfig = null;
} catch (RemoteException ex) {
    throw ex.rethrowFromSystemServer();
}

这里又是一次 Binder IPC,后续流程的调用栈如下

stopActivityLocked:3477, ActivityStack (com.android.server.am)
activityIdleInternalLocked:2092, ActivityStackSupervisor (com.android.server.am)
activityIdle:7952, ActivityManagerService (com.android.server.am)
onTransact:216, IActivityManager$Stub (android.app)
onTransact:3291, ActivityManagerService (com.android.server.am)
execTransact:731, Binder (android.os)

stopActivityLocked 又会是和 onCreate 等一样的流程,通过

mService.getLifecycleManager().scheduleTransaction(r.app.thread, r.appToken, StopActivityItem.obtain(r.visible, r.configChangeFlags));

执行了 onStop 生命周期。这其中还有很多逻辑,比如超时逻辑的处理 IDLE_TIMEOUT_MSG

2.4.2 onDestroy 的执行

onDestroy 和 onStop 其实相似,都是在 Idle 时执行的。所以和 onStop 的流程也基本一致,其中会执行 destroyActivityLocked 方法。或者主动通过 Activity.finish 调用,使得 Activity 走入 onDestroy 方法。

主动 finish 的调用栈如下:

destroyActivityLocked:4315, ActivityStack (com.android.server.am)
finishCurrentActivityLocked:3852, ActivityStack (com.android.server.am)
finishActivityLocked:3764, ActivityStack (com.android.server.am)
finishActivityLocked:3690, ActivityStack (com.android.server.am)
requestFinishActivityLocked:3530, ActivityStack (com.android.server.am)
finishActivity:5708, ActivityManagerService (com.android.server.am)
onTransact:147, IActivityManager$Stub (android.app)
onTransact:3291, ActivityManagerService (com.android.server.am)
execTransact:731, Binder (android.os)

其中 destroyActivityLocked 中关键代码如下:

mService.getLifecycleManager().scheduleTransaction(r.app.thread, r.appToken, DestroyActivityItem.obtain(r.finishing, r.configChangeFlags));

通过 Binder IPC 调用到 APP 进程执行 onDestroy 生命周期

3.剩下的两个问题

3.1 问题5

通过阅读代码也比较清晰,ActivityStack 是最大的概念,他持有多个 TaskRecord,控制哪个是前台任务等等。TaskRecord 是我们说的任务栈的概念,栈内有很多 Activity,而 ActivityRecord 是记录 Activity 的结构体。

3.2 问题4

onNewIntent 源码位置在 ActivityStarter 中 deliverNewIntent,这个方法最后会执行到 onNewIntent。

startActivityUnchecked 中可能会调用它,根据是否有 FLAG_ACTIVITY_CLEAR_TOP 标签等等。

4.总结

其实整个生命周期流程远比上面的复杂多变,包括各种情形下的生命周期变化,可能和我这里的普通情形不一致,所以可能也会导致代码流程不一致等等。

但是,这不影响对整个生命周期的认识!即使流程已经如此复杂了,但这还只是生命周期各种情形下的一小部分而已,可见启动一个 Activity 并不是很简单。

纵观整个生命周期,都伴随着各种 Binder IPC 的过程,所以 Binder 确实是 Android 的基础之一。