目录

再来看 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 的基础之一。