我们知道,Activity A启动Activity B时,是先将A暂停(执行生命周期onPause),然后会执行B的onCreate、OnStart、OnResume方法,之后再执行A的onStop。如果启动B时,它的进程不存在,会先将它的进程启动起来,再执行它的生命周期。
咱们先看简单情况下,就是不涉及进程创建这种情况下的生命周期。之前一篇文章 Android 系统进程启动Activity方法说明指出,Activity的暂停是由Task的startPausingLocked方法执行的,咱们看下它的实现。
暂停Activity
Task的startPausingLocked方法如下:
java
final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
ActivityRecord resuming, String reason) {
if (!isLeafTask()) {
final int[] pausing = {0};
forAllLeafTasks((t) -> {
if (t.startPausingLocked(userLeaving, uiSleeping, resuming, reason)) {
pausing[0]++;
}
}, true /* traverseTopToBottom */);
return pausing[0] > 0;
}
if (mPausingActivity != null) {
Slog.wtf(TAG, "Going to pause when pause is already pending for " + mPausingActivity
+ " state=" + mPausingActivity.getState());
if (!shouldSleepActivities()) {
// Avoid recursion among check for sleep and complete pause during sleeping.
// Because activity will be paused immediately after resume, just let pause
// be completed by the order of activity paused from clients.
completePauseLocked(false, resuming);
}
}
ActivityRecord prev = mResumedActivity;
if (prev == null) {
if (resuming == null) {
Slog.wtf(TAG, "Trying to pause when nothing is resumed");
mRootWindowContainer.resumeFocusedTasksTopActivities();
}
return false;
}
if (prev == resuming) {
Slog.wtf(TAG, "Trying to pause activity that is in process of being resumed");
return false;
}
ProtoLog.v(WM_DEBUG_STATES, "Moving to PAUSING: %s", prev);
mPausingActivity = prev;
mLastPausedActivity = prev;
if (prev.isNoHistory() && !mTaskSupervisor.mNoHistoryActivities.contains(prev)) {
mTaskSupervisor.mNoHistoryActivities.add(prev);
}
prev.setState(PAUSING, "startPausingLocked");
prev.getTask().touchActiveTime();
mAtmService.updateCpuStats();
boolean pauseImmediately = false;
boolean shouldAutoPip = false;
if (resuming != null && (resuming.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0) {
// If the flag RESUME_WHILE_PAUSING is set, then continue to schedule the previous
// activity to be paused, while at the same time resuming the new resume activity
// only if the previous activity can't go into Pip since we want to give Pip
// activities a chance to enter Pip before resuming the next activity.
final boolean lastResumedCanPip = prev != null && prev.checkEnterPictureInPictureState(
"shouldResumeWhilePausing", userLeaving);
if (lastResumedCanPip && prev.pictureInPictureArgs.isAutoEnterEnabled()) {
shouldAutoPip = true;
} else if (!lastResumedCanPip) {
pauseImmediately = true;
} else {
// The previous activity may still enter PIP even though it did not allow auto-PIP.
}
}
boolean didAutoPip = false;
if (prev.attachedToProcess()) {
if (shouldAutoPip) {
ProtoLog.d(WM_DEBUG_STATES, "Auto-PIP allowed, entering PIP mode "
+ "directly: %s", prev);
didAutoPip = mAtmService.enterPictureInPictureMode(prev, prev.pictureInPictureArgs);
mPausingActivity = null;
} else {
ProtoLog.v(WM_DEBUG_STATES, "Enqueueing pending pause: %s", prev);
try {
EventLogTags.writeWmPauseActivity(prev.mUserId, System.identityHashCode(prev),
prev.shortComponentName, "userLeaving=" + userLeaving, reason);
mAtmService.getLifecycleManager().scheduleTransaction(prev.app.getThread(),
prev.appToken, PauseActivityItem.obtain(prev.finishing, userLeaving,
prev.configChangeFlags, pauseImmediately));
} catch (Exception e) {
// Ignore exception, if process died other code will cleanup.
Slog.w(TAG, "Exception thrown during pause", e);
mPausingActivity = null;
mLastPausedActivity = null;
mTaskSupervisor.mNoHistoryActivities.remove(prev);
}
}
} else {
mPausingActivity = null;
mLastPausedActivity = null;
mTaskSupervisor.mNoHistoryActivities.remove(prev);
}
// If we are not going to sleep, we want to ensure the device is
// awake until the next activity is started.
if (!uiSleeping && !mAtmService.isSleepingOrShuttingDownLocked()) {
mTaskSupervisor.acquireLaunchWakelock();
}
// If already entered PIP mode, no need to keep pausing.
if (mPausingActivity != null && !didAutoPip) {
// Have the window manager pause its key dispatching until the new
// activity has started. If we're pausing the activity just because
// the screen is being turned off and the UI is sleeping, don't interrupt
// key dispatch; the same activity will pick it up again on wakeup.
if (!uiSleeping) {
prev.pauseKeyDispatchingLocked();
} else {
ProtoLog.v(WM_DEBUG_STATES, "Key dispatch not paused for screen off");
}
if (pauseImmediately) {
// If the caller said they don't want to wait for the pause, then complete
// the pause now.
completePauseLocked(false, resuming);
return false;
} else {
prev.schedulePauseTimeout();
return true;
}
} else {
// This activity either failed to schedule the pause or it entered PIP mode,
// so just treat it as being paused now.
ProtoLog.v(WM_DEBUG_STATES, "Activity not running or entered PiP, resuming next.");
if (resuming == null) {
mRootWindowContainer.resumeFocusedTasksTopActivities();
}
return false;
}
}
如果不是叶子任务,使用forAllLeafTasks循环到所有的叶子任务,然后调用它的startPausingLocked方法,如果该方法返回true,则将pausing[0]加1,最后循环结束后,检查pausing[0] > 0,只要有返回true,说明就有Task在执行Activity的暂停中。
mPausingActivity不为null,意味着,该Task正在暂停Activity过程中,所以在设备不睡眠的情况下,调用completePauseLocked(false, resuming)完成暂停工作。
接着将mResumedActivity赋值给变量prev。任务暂停的主要任务就是将mResumedActivity给暂停。
如果prev为null,并且resuming也为null,代表没有需要暂停的Activity,也没有需要恢复的Activity,调用mRootWindowContainer.resumeFocusedTasksTopActivities()试着恢复其他任务的Activity。这种情况,直接返回false。
如果prev==resuming,说明暂停和恢复的Activity都一样,这种情况也不行,直接返回false。
注意,看到给mPausingActivity赋值了,将它设置为prev,也就是mResumedActivity。
也给mLastPausedActivity赋值。
如果prev是没有历史记录,这里会将它加入到mTaskSupervisor.mNoHistoryActivities中。对于没有历史记录的Activity,主要是它处于停止状态,就把它们完成finished。
接着将prev设置为PAUSING状态,代表是在暂停中。
任务的touchActiveTime()是设置它的lastActiveTime为当前启动时间。
接着调用mAtmService.updateCpuStats()更新CPU状态。
如果待启动的Activity设置了FLAG_RESUME_WHILE_PAUSING标识,会检查prev能否进入PIP模式。如果可以进入,并且相关参数设置了可以自动进入,将shouldAutoPip = true,代表可以进入PIP。如果不能进入PIP模式,将pauseImmediately = true,代表需要立即执行暂停,不等待暂停完成。如果可以进入,但是没有设置自动进入,就像正常的Activity处理。
接着,如果prev已经绑定进程了,它会检查能否进入PIP模式。
1、可以进入PIP模式。检查刚才的shouldAutoPip,它为true,就调用mAtmService.enterPictureInPictureMode方法让它进入PIP模式,返回结果didAutoPip是否进入。并将mPausingActivity = null。
2、不进入PIP模式,调用ClientLifecycleManager对象的scheduleTransaction方法,去应用端执行Activity的暂停周期。该种情况下,就需要等待应用端执行完毕,给系统进程响应。
如果prev没有绑定进程,这里的处理,将mPausingActivity = null。将prev从mTaskSupervisor.mNoHistoryActivities删除。
如果系统不是进入睡眠,就确保设备唤醒直到下个Activity启动,唤醒是mTaskSupervisor.acquireLaunchWakelock()执行。
mPausingActivity != null && !didAutoPip,这个条件满足,代表没有进入PIP模式。
在这个条件下,如果屏幕没有关闭,调用prev.pauseKeyDispatchingLocked(),暂停prev的按键派发事件。
如果pauseImmediately为true,代表立即执行暂停行为,所以直接调用completePauseLocked(false, resuming),完成暂停工作。这里的第一个参数为false,代表完成暂停之后,不继续恢复其他Activity执行。接着返回false。
如果pauseImmediately为false,这里发送一个等待超时消息,超时时间为500ms。如果到时没有收到应用程序应答,这里会执行超时处理。接着返回结果true。
最后这个else里的情况,是调用ClientLifecycleManager对象的scheduleTransaction方法失败,或者进入PIP模式。如果resuming == null,调用mRootWindowContainer.resumeFocusedTasksTopActivities()重新执行恢复Activity。最后,返回false。
这个方法返回true,就是调用ClientLifecycleManager对象的scheduleTransaction方法之后,等待Activity暂停完成。
返回false的情况则是和上面的相反的情况,有以下几种情况,1、prev、resuming条件不符合。2、进入PIP模式。3、立即执行暂停完成。4、ClientLifecycleManager对象的scheduleTransaction方法执行异常。
像这个第2、3种情况,是需要参数resuming存在FLAG_RESUME_WHILE_PAUSING标识才出现的。
应用程序执行暂停
它在系统进程端是由ClientLifecycleManager对象的scheduleTransaction方法执行的
java
void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
final IApplicationThread client = transaction.getClient();
transaction.schedule();
if (!(client instanceof Binder)) {
// If client is not an instance of Binder - it's a remote call and at this point it is
// safe to recycle the object. All objects used for local calls will be recycled after
// the transaction is executed on client in ActivityThread.
transaction.recycle();
}
}
/**
* Schedule a single lifecycle request or callback to client activity.
* @param client Target client.
* @param activityToken Target activity token.
* @param stateRequest A request to move target activity to a desired lifecycle state.
* @throws RemoteException
*
* @see ClientTransactionItem
*/
void scheduleTransaction(@NonNull IApplicationThread client, @NonNull IBinder activityToken,
@NonNull ActivityLifecycleItem stateRequest) throws RemoteException {
final ClientTransaction clientTransaction = transactionWithState(client, activityToken,
stateRequest);
scheduleTransaction(clientTransaction);
}
参数里的stateRequest是PauseActivityItem.obtain(prev.finishing, userLeaving, prev.configChangeFlags, pauseImmediately),通过transactionWithState方法封装成ClientTransaction 对象。其中client是IApplicationThread ,它是应用进程端对应进程ApplicationThread的Binder代理对象,通过它可以与应用进程端通信。transaction.schedule()就是通过它的scheduleTransaction方法进入到应用进程端ApplicationThread的scheduleTransaction(ClientTransaction transaction)方法的,ApplicationThread在ActivityThread类里,看一下它的实现:
java
@Override
public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
ActivityThread.this.scheduleTransaction(transaction);
}
ActivityThread类继承ClientTransactionHandler类,scheduleTransaction方法就是在它里面实现的
java
void scheduleTransaction(ClientTransaction transaction) {
transaction.preExecute(this);
sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
}
可以看到在Binder线程中执行了transaction.preExecute(this),就直接发送EXECUTE_TRANSACTION消息,切换到应用的主线程中去执行了,而Binder线程也就执行完返回应答了。
transaction.preExecute(this)的代码看下:
java
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);
}
}
如果mActivityCallbacks存在,在这里调用它的preExecute方法,注意这里是在应用进程端执行的。
这里的mLifecycleStateRequest 是PauseActivityItem对象,它的preExecute是一个空实现。
接着咱们进入到应用进程端看下ActivityThread.H.EXECUTE_TRANSACTION的消息处理,它在ActivityThread类中H 类的handleMessage处理,看下它的实现:
java
case EXECUTE_TRANSACTION:
final ClientTransaction transaction = (ClientTransaction) msg.obj;
mTransactionExecutor.execute(transaction);
if (isSystem()) {
// Client transactions inside system process are recycled on the client side
// instead of ClientLifecycleManager to avoid being cleared before this
// message is handled.
transaction.recycle();
}
// TODO(lifecycler): Recycle locally scheduled transactions.
break;
mTransactionExecutor是TransactionExecutor类,看下它的execute(transaction)实现:
java
public void execute(ClientTransaction transaction) {
if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "Start resolving transaction");
final IBinder token = transaction.getActivityToken();
if (token != null) {
final Map<IBinder, ClientTransactionItem> activitiesToBeDestroyed =
mTransactionHandler.getActivitiesToBeDestroyed();
final ClientTransactionItem destroyItem = activitiesToBeDestroyed.get(token);
if (destroyItem != null) {
if (transaction.getLifecycleStateRequest() == destroyItem) {
// It is going to execute the transaction that will destroy activity with the
// token, so the corresponding to-be-destroyed record can be removed.
activitiesToBeDestroyed.remove(token);
}
if (mTransactionHandler.getActivityClient(token) == null) {
// The activity has not been created but has been requested to destroy, so all
// transactions for the token are just like being cancelled.
Slog.w(TAG, tId(transaction) + "Skip pre-destroyed transaction:\n"
+ transactionToString(transaction, mTransactionHandler));
return;
}
}
}
if (DEBUG_RESOLVER) Slog.d(TAG, transactionToString(transaction, mTransactionHandler));
executeCallbacks(transaction);
executeLifecycleState(transaction);
mPendingActions.clear();
if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "End resolving transaction");
}
mTransactionHandler就是ActivityThread对象,开始那些代码是处理Destory周期相关代码。
下面就是调用executeCallbacks(transaction),它是用来执行ClientTransaction对象添加的回调事件,像ActivityResultItem、NewIntentItem,它们分别对应着Activity中onActivityResult、onNewIntent方法的调用。
executeLifecycleState(transaction)就是用来执行Activity的生命周期的,看下它的实现:
java
private void executeLifecycleState(ClientTransaction transaction) {
final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();
if (lifecycleItem == null) {
// No lifecycle request, return early.
return;
}
final IBinder token = transaction.getActivityToken();
final ActivityClientRecord r = mTransactionHandler.getActivityClient(token);
if (DEBUG_RESOLVER) {
Slog.d(TAG, tId(transaction) + "Resolving lifecycle state: "
+ lifecycleItem + " for activity: "
+ getShortActivityName(token, mTransactionHandler));
}
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 */, transaction);
// Execute the final transition with proper parameters.
lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
}
这里transaction.getLifecycleStateRequest()得到的lifecycleItem是PauseActivityItem对象,通过token得到在应用端的ActivityClientRecord 对象r。
cycleToPath方法是用来处理Activity生命周期的,第三个参数表示是否执行最后一个状态的生命周期,如果为true,不执行。最后一个的生命周期就是通过下面lifecycleItem.execute来执行的。
最后执行lifecycleItem.postExecute方法,PauseActivityItem的类的处理是通知系统进程它暂停完了。
看下cycleToPath方法的实现:
java
private void cycleToPath(ActivityClientRecord r, int finish, boolean excludeLastState,
ClientTransaction transaction) {
final int start = r.getLifecycleState();
if (DEBUG_RESOLVER) {
Slog.d(TAG, tId(transaction) + "Cycle activity: "
+ getShortActivityName(r.token, mTransactionHandler)
+ " from: " + getStateName(start) + " to: " + getStateName(finish)
+ " excludeLastState: " + excludeLastState);
}
final IntArray path = mHelper.getLifecyclePath(start, finish, excludeLastState);
performLifecycleSequence(r, path, transaction);
}
start 是Activity开始的生命周期,finish是Activity最后要完成的生命周期,所以mHelper.getLifecyclePath方法来计算出来要经过哪些生命周期,计算出来放到IntArray 类型变量path 中。
像我们这个暂停周期,因为Activity目前是onResume,并且excludeLastState目前为true,需要排除掉onPause,所以path 是空的,不会执行。
performLifecycleSequence(r, path, transaction)就是来执行它的具体生命周期。看下它的实现:
java
private void performLifecycleSequence(ActivityClientRecord r, IntArray path,
ClientTransaction transaction) {
final int size = path.size();
for (int i = 0, state; i < size; i++) {
state = path.get(i);
if (DEBUG_RESOLVER) {
Slog.d(TAG, tId(transaction) + "Transitioning activity: "
+ getShortActivityName(r.token, mTransactionHandler)
+ " to state: " + getStateName(state));
}
switch (state) {
case ON_CREATE:
mTransactionHandler.handleLaunchActivity(r, mPendingActions,
null /* customIntent */);
break;
case ON_START:
mTransactionHandler.handleStartActivity(r, mPendingActions,
null /* activityOptions */);
break;
case ON_RESUME:
mTransactionHandler.handleResumeActivity(r, false /* finalStateRequest */,
r.isForward, "LIFECYCLER_RESUME_ACTIVITY");
break;
case ON_PAUSE:
mTransactionHandler.handlePauseActivity(r, false /* finished */,
false /* userLeaving */, 0 /* configChanges */, mPendingActions,
"LIFECYCLER_PAUSE_ACTIVITY");
break;
case ON_STOP:
mTransactionHandler.handleStopActivity(r, 0 /* configChanges */,
mPendingActions, false /* finalStateRequest */,
"LIFECYCLER_STOP_ACTIVITY");
break;
case ON_DESTROY:
mTransactionHandler.handleDestroyActivity(r, false /* finishing */,
0 /* configChanges */, false /* getNonConfigInstance */,
"performLifecycleSequence. cycling to:" + path.get(size - 1));
break;
case ON_RESTART:
mTransactionHandler.performRestartActivity(r, false /* start */);
break;
default:
throw new IllegalArgumentException("Unexpected lifecycle state: " + state);
}
}
}
mTransactionHandler就是ActivityThread对象,所以我们看到它根据生命周期路径值,来执行对应的生命周期。
接着看回我们的PauseActivityItem对象的execute方法。
java
@Override
public void execute(ClientTransactionHandler client, ActivityClientRecord r,
PendingTransactionActions pendingActions) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
client.handlePauseActivity(r, mFinished, mUserLeaving, mConfigChanges, pendingActions,
"PAUSE_ACTIVITY_ITEM");
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
这里client是ActivityThread对象,所以就执行到了它的handlePauseActivity方法。
java
@Override
public void handlePauseActivity(ActivityClientRecord r, boolean finished, boolean userLeaving,
int configChanges, PendingTransactionActions pendingActions, String reason) {
if (userLeaving) {
performUserLeavingActivity(r);
}
r.activity.mConfigChangeFlags |= configChanges;
performPauseActivity(r, finished, reason, pendingActions);
// Make sure any pending writes are now committed.
if (r.isPreHoneycomb()) {
QueuedWork.waitToFinish();
}
mSomeActivitiesChanged = true;
}
这里处理了userLeaving,如果它为true,会在onPause之前执行Activity的onUserLeaveHint()。
接着将配置更改并到Activity的mConfigChangeFlags 中。
执行performPauseActivity来执行Activity的onPause生命周期。
如果Activity的应用的targetSdkVersion小于HONEYCOMB,这里确保所有的写工作都被确认。
主要来看一下performPauseActivity方法
java
private Bundle performPauseActivity(ActivityClientRecord r, boolean finished, String reason,
PendingTransactionActions pendingActions) {
if (r.paused) {
if (r.activity.mFinished) {
// If we are finishing, we won't call onResume() in certain cases.
// So here we likewise don't want to call onPause() if the activity
// isn't resumed.
return null;
}
RuntimeException e = new RuntimeException(
"Performing pause of activity that is not resumed: "
+ r.intent.getComponent().toShortString());
Slog.e(TAG, e.getMessage(), e);
}
if (finished) {
r.activity.mFinished = true;
}
// Pre-Honeycomb apps always save their state before pausing
final boolean shouldSaveState = !r.activity.mFinished && r.isPreHoneycomb();
if (shouldSaveState) {
callActivityOnSaveInstanceState(r);
}
performPauseActivityIfNeeded(r, reason);
// Notify any outstanding on paused listeners
ArrayList<OnActivityPausedListener> listeners;
synchronized (mOnPauseListeners) {
listeners = mOnPauseListeners.remove(r.activity);
}
int size = (listeners != null ? listeners.size() : 0);
for (int i = 0; i < size; i++) {
listeners.get(i).onPaused(r.activity);
}
final Bundle oldState = pendingActions != null ? pendingActions.getOldState() : null;
if (oldState != null) {
// We need to keep around the original state, in case we need to be created again.
// But we only do this for pre-Honeycomb apps, which always save their state when
// pausing, so we can not have them save their state when restarting from a paused
// state. For HC and later, we want to (and can) let the state be saved as the
// normal part of stopping the activity.
if (r.isPreHoneycomb()) {
r.state = oldState;
}
}
return shouldSaveState ? r.state : null;
}
如果ActivityClientRecord已经是paused,并且Activity已经是mFinished,直接返回,不再往下执行。
如果参数finished为true,这里将r.activity.mFinished = true,这里是将系统进程中的状态同步到应用进程中。
如果Activity的应用的targetSdkVersion小于HONEYCOMB,并且Activity不是mFinished,这时需要调用Activity的OnSaveInstanceState方法,来保存数据。
接着就是执行performPauseActivityIfNeeded方法,执行Activity的onPause方法。
下面是如果ActivityThread对象注册了OnActivityPausedListener回调,这里调用它。
接着看performPauseActivityIfNeeded方法,
java
private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) {
if (r.paused) {
// You are already paused silly...
return;
}
// Always reporting top resumed position loss when pausing an activity. If necessary, it
// will be restored in performResumeActivity().
reportTopResumedActivityChanged(r, false /* onTop */, "pausing");
try {
r.activity.mCalled = false;
mInstrumentation.callActivityOnPause(r.activity);
if (!r.activity.mCalled) {
throw new SuperNotCalledException("Activity " + safeToComponentShortString(r.intent)
+ " did not call through to super.onPause()");
}
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
if (!mInstrumentation.onException(r.activity, e)) {
throw new RuntimeException("Unable to pause activity "
+ safeToComponentShortString(r.intent) + ": " + e.toString(), e);
}
}
r.setState(ON_PAUSE);
}
可以看到调用了mInstrumentation.callActivityOnPause(r.activity),mInstrumentation是Instrumentation对象,它直接执行Activity对象的performPause()方法。
最后调用了r.setState(ON_PAUSE)设置它的对应状态,他会将ActivityClientRecord 对象的paused = true,stopped = false。
主要看Activity对象的performPause()方法
java
final void performPause() {
if (Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "performPause:"
+ mComponent.getClassName());
}
dispatchActivityPrePaused();
mDoReportFullyDrawn = false;
mFragments.dispatchPause();
mCalled = false;
onPause();
EventLogTags.writeWmOnPausedCalled(mIdent, getComponentName().getClassName(),
"performPause");
mResumed = false;
if (!mCalled && getApplicationInfo().targetSdkVersion
>= android.os.Build.VERSION_CODES.GINGERBREAD) {
throw new SuperNotCalledException(
"Activity " + mComponent.toShortString() +
" did not call through to super.onPause()");
}
dispatchActivityPostPaused();
Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
}
dispatchActivityPrePaused()是用来执行一些暂停前回调。
mFragments.dispatchPause()用来设置Activiyt中的Fragment对象的生命周期暂停。
调用Activity的onPause()生命周期方法。
mResumed = false
dispatchActivityPostPaused()是用来执行一些暂停后回调。
系统进程处理Activity暂停完毕
它是在PauseActivityItem的postExecute方法完成,看下它的实现:
java
@Override
public void postExecute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
if (mDontReport) {
return;
}
// TODO(lifecycler): Use interface callback instead of actual implementation.
ActivityClient.getInstance().activityPaused(token);
}
如果mDontReport为true,则不通知系统进程。像立即执行暂停的Activity就不会执行下面的通知。
调用ActivityClient类对象的activityPaused方法,调用的是系统进程端ActivityClientController对象的代理对象的activityPaused方法。这里直接到ActivityClientController类中看下activityPaused方法的实现:
java
@Override
public void activityPaused(IBinder token) {
final long origId = Binder.clearCallingIdentity();
synchronized (mGlobalLock) {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "activityPaused");
final ActivityRecord r = ActivityRecord.forTokenLocked(token);
if (r != null) {
r.activityPaused(false);
}
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
Binder.restoreCallingIdentity(origId);
}
这里通过参数token得到系统进程端的ActivityRecord ,直接执行它的activityPaused方法。看下它的方法
java
void activityPaused(boolean timeout) {
ProtoLog.v(WM_DEBUG_STATES, "Activity paused: token=%s, timeout=%b", appToken,
timeout);
if (task != null) {
removePauseTimeout();
final ActivityRecord pausingActivity = task.getPausingActivity();
if (pausingActivity == this) {
ProtoLog.v(WM_DEBUG_STATES, "Moving to PAUSED: %s %s", this,
(timeout ? "(due to timeout)" : " (pause complete)"));
mAtmService.deferWindowLayout();
try {
task.completePauseLocked(true /* resumeNext */, null /* resumingActivity */);
} finally {
mAtmService.continueWindowLayout();
}
return;
} else {
EventLogTags.writeWmFailedToPause(mUserId, System.identityHashCode(this),
shortComponentName, pausingActivity != null
? pausingActivity.shortComponentName : "(none)");
if (isState(PAUSING)) {
setState(PAUSED, "activityPausedLocked");
if (finishing) {
ProtoLog.v(WM_DEBUG_STATES,
"Executing finish of failed to pause activity: %s", this);
completeFinishing("activityPausedLocked");
}
}
}
}
mDisplayContent.handleActivitySizeCompatModeIfNeeded(this);
mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
}
首先取消暂停的超时消息,调用的是removePauseTimeout()。
如果任务中pausingActivity和目前的相等,就去执行它的completePauseLocked方法,完成它的暂停工作。
如果不相等,它的状态如果为PAUSING(暂停中),将它的状态设置为PAUSED。并且如果Activity的finishing为true,调用completeFinishing方法结束它。
接着调用mDisplayContent.handleActivitySizeCompatModeIfNeeded(this)检查Activity是在兼容模式并且通知它的改变。
最后调用mRootWindowContainer.ensureActivitiesVisible方法,使所有Activity的可见性保持正确。
接着看任务的completePauseLocked方法,看它完成暂停工作。并且它的第一个参数为true,会暂停完成之后,就去执行新Activity的恢复执行。看下它的代码,在Task类中:
java
@VisibleForTesting
void completePauseLocked(boolean resumeNext, ActivityRecord resuming) {
// Complete the pausing process of a pausing activity, so it doesn't make sense to
// operate on non-leaf tasks.
warnForNonLeafTask("completePauseLocked");
ActivityRecord prev = mPausingActivity;
ProtoLog.v(WM_DEBUG_STATES, "Complete pause: %s", prev);
if (prev != null) {
prev.setWillCloseOrEnterPip(false);
final boolean wasStopping = prev.isState(STOPPING);
prev.setState(PAUSED, "completePausedLocked");
if (prev.finishing) {
// We will update the activity visibility later, no need to do in
// completeFinishing(). Updating visibility here might also making the next
// activities to be resumed, and could result in wrong app transition due to
// lack of previous activity information.
ProtoLog.v(WM_DEBUG_STATES, "Executing finish of activity: %s", prev);
prev = prev.completeFinishing(false /* updateVisibility */,
"completePausedLocked");
} else if (prev.hasProcess()) {
ProtoLog.v(WM_DEBUG_STATES, "Enqueue pending stop if needed: %s "
+ "wasStopping=%b visibleRequested=%b", prev, wasStopping,
prev.mVisibleRequested);
if (prev.deferRelaunchUntilPaused) {
// Complete the deferred relaunch that was waiting for pause to complete.
ProtoLog.v(WM_DEBUG_STATES, "Re-launching after pause: %s", prev);
prev.relaunchActivityLocked(prev.preserveWindowOnDeferredRelaunch);
} else if (wasStopping) {
// We are also stopping, the stop request must have gone soon after the pause.
// We can't clobber it, because the stop confirmation will not be handled.
// We don't need to schedule another stop, we only need to let it happen.
prev.setState(STOPPING, "completePausedLocked");
} else if (!prev.mVisibleRequested || shouldSleepOrShutDownActivities()) {
// Clear out any deferred client hide we might currently have.
prev.setDeferHidingClient(false);
// If we were visible then resumeTopActivities will release resources before
// stopping.
prev.addToStopping(true /* scheduleIdle */, false /* idleDelayed */,
"completePauseLocked");
}
} else {
ProtoLog.v(WM_DEBUG_STATES, "App died during pause, not stopping: %s", prev);
prev = null;
}
// It is possible the activity was freezing the screen before it was paused.
// In that case go ahead and remove the freeze this activity has on the screen
// since it is no longer visible.
if (prev != null) {
prev.stopFreezingScreenLocked(true /*force*/);
}
mPausingActivity = null;
}
if (resumeNext) {
final Task topRootTask = mRootWindowContainer.getTopDisplayFocusedRootTask();
if (topRootTask != null && !topRootTask.shouldSleepOrShutDownActivities()) {
mRootWindowContainer.resumeFocusedTasksTopActivities(topRootTask, prev, null);
} else {
checkReadyForSleep();
final ActivityRecord top =
topRootTask != null ? topRootTask.topRunningActivity() : null;
if (top == null || (prev != null && top != prev)) {
// If there are no more activities available to run, do resume anyway to start
// something. Also if the top activity on the root task is not the just paused
// activity, we need to go ahead and resume it to ensure we complete an
// in-flight app switch.
mRootWindowContainer.resumeFocusedTasksTopActivities();
}
}
}
if (prev != null) {
prev.resumeKeyDispatchingLocked();
}
mRootWindowContainer.ensureActivitiesVisible(resuming, 0, !PRESERVE_WINDOWS);
// Notify when the task stack has changed, but only if visibilities changed (not just
// focus). Also if there is an active root pinned task - we always want to notify it about
// task stack changes, because its positioning may depend on it.
if (mTaskSupervisor.mAppVisibilitiesChangedSinceLastPause
|| (getDisplayArea() != null && getDisplayArea().hasPinnedTask())) {
mAtmService.getTaskChangeNotificationController().notifyTaskStackChanged();
mTaskSupervisor.mAppVisibilitiesChangedSinceLastPause = false;
}
}
将mPausingActivity赋值为prev。
设置它不是在关闭或打开PIP的过程中。
判断prev是不是STOPPING状态,保存在wasStopping中。
并且将prev的状态设置为PAUSED,代表暂停状态完成。
如果prev已经是finishing,则调用它的completeFinishing完成finishing。
如果不是finishing状态,并且它有进程。这种情况下,又分了几种情况处理:
1、prev.deferRelaunchUntilPaused为true,代表延缓重启直到暂停完成,这里就调用它的relaunchActivityLocked方法,重新启动。
2、prev在设置PAUSED状态之前是STOPPING状态,在这里将它设置为STOPPING状态。
3、prev处于不可见状态,或者系统将睡眠或者关闭状态,清除掉prev的延缓客户端隐藏状态,并且将它添加到mTaskSupervisor.mStoppingActivities中,mTaskSupervisor.mStoppingActivities和prev的onStop周期执行相关。
接着调用prev.stopFreezingScreenLocked(true /force /),停止冻结屏幕。
这里就会将mPausingActivity = null。
如果参数resumeNext为true,代表需要恢复Activity执行。
如果mRootWindowContainer最顶端根任务不为null,并且系统不是将睡眠或关闭,这种情况下,调用mRootWindowContainer.resumeFocusedTasksTopActivities方法去执行Activity的恢复启动。这是第二次调用它的情况,详细参考这篇 Android 系统进程启动Activity方法说明。
如果不符合上面这种情况,系统准备睡眠。如果顶层根任务没有可运行Activity,或者可运行Activity不等于prev,这个时候,也调用mRootWindowContainer.resumeFocusedTasksTopActivities()。
接下来,如果prev不为null,则恢复它的按键派发。
mRootWindowContainer.ensureActivitiesVisible方法来确保Activity的可见性。这个步骤里面会检测到上面的prev对象,不可见,因为它被遮挡了,所以会执行它的makeInvisible(),在该方法中,会设置它的可见性为false。并且如果它的状态为PAUSED,会将它添加到mTaskSupervisor.mStoppingActivities中,因为这块会影响到onStop生命周期的执行,这里要说一下。
如果Activity的可见性发生变化,或者TaskDisplayArea对象存在PinnedTask,这时发送任务栈改变的通知。
Activity恢复启动
如果暂停完成之后,待启动的Activity是新创建的Activity,在第二次执行Task类的resumeTopActivityInnerLocked方法时,启动的Activity是还没有绑定到进程上呢,即next.attachedToProcess()为false。详细见 Android 系统进程启动Activity方法说明。这个时候,它会调用ActivityTaskSupervisor类对象的startSpecificActivity方法,这里呢,咱们说简单的,进程已经存在的情况,看下它对应情况下的Activity生命周期执行。它调用的是ActivityTaskSupervisor类对象的realStartActivityLocked方法:
java
boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
boolean andResume, boolean checkConfig) throws RemoteException {
............
r.setProcess(proc);
............
// Create activity launch transaction.
final ClientTransaction clientTransaction = ClientTransaction.obtain(
proc.getThread(), r.appToken);
final boolean isTransitionForward = r.isTransitionForward();
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, proc.getReportedProcState(),
r.getSavedState(), r.getPersistentSavedState(), results, newIntents,
r.takeOptions(), isTransitionForward,
proc.createProfilerInfoIfNeeded(), r.assistToken, activityClientController,
r.createFixedRotationAdjustmentsIfNeeded(), r.shareableActivityToken,
r.getLaunchedFromBubble()));
// Set desired final state.
final ActivityLifecycleItem lifecycleItem;
if (andResume) {
lifecycleItem = ResumeActivityItem.obtain(isTransitionForward);
} else {
lifecycleItem = PauseActivityItem.obtain();
}
clientTransaction.setLifecycleStateRequest(lifecycleItem);
// Schedule transaction.
mService.getLifecycleManager().scheduleTransaction(clientTransaction);
这里只将生命周期相关的方法贴出来,其他的省略了。
这里调用r.setProcess(proc)将Activity与进程绑定起来。其实就是将Activity类对象的app指向proc。
接着就和调度Pause事件比较相似了。
也是先构造一个ClientTransaction类对象clientTransaction。
这里它增加了一个LaunchActivityItem回调。
然后根据参数andResume,来将ResumeActivityItem还是PauseActivityItem设置到clientTransaction对象的mLifecycleStateRequest中。像我们这种情况,参数andResume为true,所以设置的是ResumeActivityItem类对象。
接着就是开始调度clientTransaction。
这些方法和前面暂停周期事件,是相似的,这里说下不一样的地方。
因为ClientTransaction带LaunchActivityItem回调,所以差异就在LaunchActivityItem回调。
1、它们先执行LaunchActivityItem的preExecute方法,然后执行ResumeActivityItem的preExecute方法。
2、再切换到应用主线程中执行LaunchActivityItem的execute方法,然后再执行LaunchActivityItem的postExecute。
3、执行ResumeActivityItem的execute方法,再继续执行ResumeActivityItem的postExecute方法。在执行ResumeActivityItem的execute方法之前,还会将它们之间的生命周期执行一遍。
先看一下,LaunchActivityItem类的preExecute方法,
java
@Override
public void preExecute(ClientTransactionHandler client, IBinder token) {
ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
mPendingResults, mPendingNewIntents, mActivityOptions, mIsForward, mProfilerInfo,
client, mAssistToken, mFixedRotationAdjustments, mShareableActivityToken,
mLaunchedFromBubble);
client.addLaunchingActivity(token, r);
client.updateProcessState(mProcState, false);
client.updatePendingConfiguration(mCurConfig);
if (mActivityClientController != null) {
ActivityClient.setActivityClientController(mActivityClientController);
}
}
在这里首先创建ActivityClientRecord 类对象r。
接着将它添加到ActivityThread对象的成员mLaunchingActivities中,client就是ActivityThread对象。
其他的就是更新进程相关信息和配置。
ResumeActivityItem类的preExecute方法也是更新进程状态,这里略过。
LaunchActivityItem的execute方法,
java
@Override
public void execute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
ActivityClientRecord r = client.getLaunchingActivity(token);
client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
这里首先将上面添加到mLaunchingActivities中的ActivityClientRecord 类对象取出来。
执行ActivityThread的handleLaunchActivity方法。它的方法如下:
java
@Override
public Activity handleLaunchActivity(ActivityClientRecord r,
PendingTransactionActions pendingActions, Intent customIntent) {
............
final Activity a = performLaunchActivity(r, customIntent);
............
return a;
}
主要是执行performLaunchActivity方法:
java
/** Core implementation of activity launch. */
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
............
java.lang.ClassLoader cl = appContext.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
............
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
............
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
............
r.setState(ON_CREATE);
// updatePendingActivityConfiguration() reads from mActivities to update
// ActivityClientRecord which runs in a different thread. Protect modifications to
// mActivities to avoid race.
synchronized (mResourcesManager) {
mActivities.put(r.token, r);
}
............
performLaunchActivity通过mInstrumentation.newActivity方法创建了Activity 对象activity 。
r.packageInfo.makeApplication方法创建了Application 类对象。
通过mInstrumentation.callActivityOnCreate方法调用Activity 对象的onCreate方法。
将ActivityClientRecord类对象状态设置为ON_CREATE,等会计算ON_RESUME之间的生命周期会使用。
并将ActivityClientRecord类对象放入mActivities中。
再看LaunchActivityItem的postExecute方法,
java
@Override
public void postExecute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
client.removeLaunchingActivity(token);
}
将ActivityClientRecord类对象从mLaunchingActivities删除掉。
看ResumeActivityItem和当前Activity生命周期路径,因为ResumeActivityItem的getTargetState()为ON_RESUME,所以生命周期路径为[ON_START],所以会执行ActivityThread类对象的handleStartActivity方法,它里面会调用Activity的onStart方法。
再看看ResumeActivityItem的execute方法:
java
@Override
public void execute(ClientTransactionHandler client, ActivityClientRecord r,
PendingTransactionActions pendingActions) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityResume");
client.handleResumeActivity(r, true /* finalStateRequest */, mIsForward,
"RESUME_ACTIVITY");
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
可以看到还是执行了ActivityThread类对象的handleResumeActivity方法。
java
@Override
public void handleResumeActivity(ActivityClientRecord r, boolean finalStateRequest,
boolean isForward, String reason) {
............
if (!performResumeActivity(r, finalStateRequest, reason)) {
return;
}
............
mNewActivities = r;
Looper.myQueue().addIdleHandler(new Idler());
可见它执行了performResumeActivity方法,该方法里面调用了Activity的onResume方法。代表Activity恢复执行了。
将启动的ActivityClientRecord对象赋值给mNewActivities 。
最后向消息对列中添加一个Idler对象。
Activity停止
向消息对垒中添加的Idler对象消息,在主线程空闲时,会执行它的queueIdle(),看下它的执行。
java
private class Idler implements MessageQueue.IdleHandler {
@Override
public final boolean queueIdle() {
ActivityClientRecord a = mNewActivities;
boolean stopProfiling = false;
if (mBoundApplication != null && mProfiler.profileFd != null
&& mProfiler.autoStopProfiler) {
stopProfiling = true;
}
if (a != null) {
mNewActivities = null;
final ActivityClient ac = ActivityClient.getInstance();
ActivityClientRecord prev;
do {
if (localLOGV) Slog.v(
TAG, "Reporting idle of " + a +
" finished=" +
(a.activity != null && a.activity.mFinished));
if (a.activity != null && !a.activity.mFinished) {
ac.activityIdle(a.token, a.createdConfig, stopProfiling);
a.createdConfig = null;
}
prev = a;
a = a.nextIdle;
prev.nextIdle = null;
} while (a != null);
}
if (stopProfiling) {
mProfiler.stopProfiling();
}
applyPendingProcessState();
return false;
}
}
它会在mNewActivities不为null的情况下,执行ActivityClient对象的activityIdle方法,它会通过Binder调用系统进程端ActivityClientController对象的activityIdle方法,
java
@Override
public void activityIdle(IBinder token, Configuration config, boolean stopProfiling) {
final long origId = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "activityIdle");
final ActivityRecord r = ActivityRecord.forTokenLocked(token);
if (r == null) {
return;
}
mTaskSupervisor.activityIdleInternal(r, false /* fromTimeout */,
false /* processPausingActivities */, config);
if (stopProfiling && r.hasProcess()) {
r.app.clearProfilerIfNeeded();
}
}
} finally {
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
Binder.restoreCallingIdentity(origId);
}
}
它主要调用mTaskSupervisor.activityIdleInternal方法,而activityIdleInternal方法里面会调用processStoppingAndFinishingActivities方法,
java
private void processStoppingAndFinishingActivities(ActivityRecord launchedActivity,
boolean processPausingActivities, String reason) {
// Stop any activities that are scheduled to do so but have been waiting for the transition
// animation to finish.
ArrayList<ActivityRecord> readyToStopActivities = null;
for (int i = mStoppingActivities.size() - 1; i >= 0; --i) {
final ActivityRecord s = mStoppingActivities.get(i);
final boolean animating = s.isAnimating(TRANSITION | PARENTS,
ANIMATION_TYPE_APP_TRANSITION | ANIMATION_TYPE_RECENTS)
|| mService.getTransitionController().inTransition(s);
ProtoLog.v(WM_DEBUG_STATES, "Stopping %s: nowVisible=%b animating=%b "
+ "finishing=%s", s, s.nowVisible, animating, s.finishing);
if (!animating || mService.mShuttingDown) {
if (!processPausingActivities && s.isState(PAUSING)) {
// Defer processing pausing activities in this iteration and reschedule
// a delayed idle to reprocess it again
removeIdleTimeoutForActivity(launchedActivity);
scheduleIdleTimeout(launchedActivity);
continue;
}
ProtoLog.v(WM_DEBUG_STATES, "Ready to stop: %s", s);
if (readyToStopActivities == null) {
readyToStopActivities = new ArrayList<>();
}
readyToStopActivities.add(s);
mStoppingActivities.remove(i);
}
}
final int numReadyStops = readyToStopActivities == null ? 0 : readyToStopActivities.size();
for (int i = 0; i < numReadyStops; i++) {
final ActivityRecord r = readyToStopActivities.get(i);
if (r.isInHistory()) {
if (r.finishing) {
// TODO(b/137329632): Wait for idle of the right activity, not just any.
r.destroyIfPossible(reason);
} else {
r.stopIfPossible();
}
}
}
............
可见这里就是从mTaskSupervisor的mStoppingActivities集合中取出来,然后调用ActivityRecord的stopIfPossible()方法。
而stopIfPossible()方法又通过构造StopActivityItem,组成ClientTransaction对象进行调度。而之前的暂停的Activity目前是onPause状态,所以就执行StopActivityItem的execute方法:
java
@Override
public void execute(ClientTransactionHandler client, ActivityClientRecord r,
PendingTransactionActions pendingActions) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStop");
client.handleStopActivity(r, mConfigChanges, pendingActions,
true /* finalStateRequest */, "STOP_ACTIVITY_ITEM");
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
可见还是通过ActivityThread对象的handleStopActivity来执行Activity的onStop。
StopActivityItem的postExecute方法,还是在执行完停止之后,向系统进程发送应答。这样,会将系统端ActivityRecord对象的状态设置为STOPPED。
总结
这里过了一遍进程存在情况下的Activity启动的整体流程,主要是观察对应声明周期方法的执行。
可以看到,系统进程端会将对应周期类封装到ClientTransaction类对象进行调度,不同的周期类实现不同的preExecute、execute、postExecute方法。并且ClientTransaction还能添加回调,实现不同功能。