再来看 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 等各种相关流程)
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 的基础之一。