本文基于 android-10.0.0_r41 版本讲解
上一节说到调用 mRootActivityContainer.resumeFocusedStacksTopActivities
onPause 前一个 Activity。
需要注意的一点是: resumeFocusedStacksTopActivities
从方法名看上去,好像是要 resume 目标 Activity,实际上,当前情景下,只是 pause 启动端 Activity,也就是 pause Launcher Activity
接下来我们来看源码实现:
java
// frameworks/base/services/core/java/com/android/server/wm/RootActivityContainer.java
boolean resumeFocusedStacksTopActivities(
ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
if (!mStackSupervisor.readyToResume()) {
return false;
}
boolean result = false;
if (targetStack != null && (targetStack.isTopStackOnDisplay()
|| getTopDisplayFocusedStack() == targetStack)) {
// 关注点
result = targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
}
// ......
return result;
}
经过一些状态的判断后,接着调用 resumeTopActivityUncheckedLocked 方法:
java
// /frameworks/base/services/core/java/com/android/server/wm/ActivityStack.java
// 注意当前方法所在的对象是 targetStack 就是待启动的目标 Activity 所在的 ActivityStack
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
if (mInResumeTopActivity) {
// Don't even start recursing.
return false;
}
boolean result = false;
try {
// Protect against recursion.
mInResumeTopActivity = true;
// 关注点
result = resumeTopActivityInnerLocked(prev, options);
// resume 过程中,如果锁屏了,sleep 当前 Activity
// 当前是 onPause 过程,关系不大
// When resuming the top activity, it may be necessary to pause the top activity (for
// example, returning to the lock screen. We suppress the normal pause logic in
// {@link #resumeTopActivityUncheckedLocked}, since the top activity is resumed at the
// end. We call the {@link ActivityStackSupervisor#checkReadyForSleepLocked} again here
// to ensure any necessary pause logic occurs. In the case where the Activity will be
// shown regardless of the lock screen, the call to
// {@link ActivityStackSupervisor#checkReadyForSleepLocked} is skipped.
final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
if (next == null || !next.canTurnScreenOn()) {
checkReadyForSleep();
}
} finally {
mInResumeTopActivity = false;
}
return result;
}
接着调用 resumeTopActivityInnerLocked
方法,需要注意的是:
- 这个时候,内部的数据结构(ActivityRecord TaskRecord ActivityStack)都设置好了。
- resumeTopActivityInnerLocked 是 ActivityStack 对象的成员函数,当前方法所在的对象是 targetStack ,就是待启动的目标 Activity 所在的 ActivityStack
- 方法参数 pre 名字有点迷惑,实际上 pre 对应的 Activity 是目标待启动 Activity
java
// /frameworks/base/services/core/java/com/android/server/wm/ActivityStack.java
/*
ActivityRecord prev:目标 Activity 的相关信息
ActivityOptions options:额外附加信息
*/
@GuardedBy("mService")
private boolean resumeTopActivityInnerLocked (ActivityRecord prev, ActivityOptions options) {
// 如果系统还未启动完毕,那 AMS 还不能正常工作,所以也不能显示 Activity,主要是为防止没有开机启动完成
if (!mService.isBooting() && !mService.isBooted()) {
// Not ready yet!
return false;
}
// 就是目标 Activity,和参数中的 pre 是同一个对象
// 因为内部数据结构(ActivityRecord TaskRecord ActivityStack)都安排好了,所以 topRunningActivityLocked 获取到的就是目标 Activity
// 但是实际上那个目标 Activity 还没有 Running
ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
final boolean hasRunningActivity = next != null;
// ......
// 当前可能存在一些正处于 Intializing 状态的 ActivityRecord,
// 如果这些 ActivityRecord 不是位于栈顶,而且正在执行窗口启动动画,
// 那么,就需要取消这些 Activity 的启动动画。
mRootActivityContainer.cancelInitializingActivities();
//这个变量是表示是否回调 Activity 中的 onUserLeaveHint 和 onUserInteraction 函数
// Remember how we'll process this pause/resume situation, and ensure
// that the state is reset however we wind up proceeding.
boolean userLeaving = mStackSupervisor.mUserLeaving;
mStackSupervisor.mUserLeaving = false;
//......
next.delayedResume = false;
final ActivityDisplay display = getDisplay();
// ......
/*
在 mStackSupervisor 中存在很多的数据结构,用来统一管理 ActivityRecord 的状态
mStoppingActivities 记录了当前所有处于 Stopping 状态的 ActivityRecord
mGoingToSleepActivities 记录了当前所有要进入休眠状态的 ActivityRecord
在某些场景下,待显示的 ActivityRecord 可能处于这些数组中,需要从中剔除
*/
// The activity may be waiting for stop, but that is no longer
// appropriate for it.
mStackSupervisor.mStoppingActivities.remove(next);
mStackSupervisor.mGoingToSleepActivities.remove(next);
next.sleeping = false;
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next);
// ......
/*
setLaunchSource 设置待启动的 Activity 的信息
跟进 setLaunchSource 源码发现它最终会获取一个 WakeLock,保证在显示 Activity 的过程中,系统不会进行休眠状态
*/
mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid);
boolean lastResumedCanPip = false;
ActivityRecord lastResumed = null;
final ActivityStack lastFocusedStack = display.getLastFocusedStack();
if (lastFocusedStack != null && lastFocusedStack != this) { // 进入
// So, why aren't we using prev here??? See the param comment on the method. prev doesn't
// represent the last resumed activity. However, the last focus stack does if it isn't null.
lastResumed = lastFocusedStack.mResumedActivity;
if (userLeaving && inMultiWindowMode() && lastFocusedStack.shouldBeVisible(next)) {
// The user isn't leaving if this stack is the multi-window mode and the last
// focused stack should still be visible.
if(DEBUG_USER_LEAVING) Slog.i(TAG_USER_LEAVING, "Overriding userLeaving to false"
+ " next=" + next + " lastResumed=" + lastResumed);
userLeaving = false;
}
lastResumedCanPip = lastResumed != null && lastResumed.checkEnterPictureInPictureState(
"resumeTopActivity", userLeaving /* beforeStopping */);
}
// 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 resumeWhilePausing = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0
&& !lastResumedCanPip; // false
/*
开始 Pause Activity
*/
boolean pausing = getDisplay().pauseBackStacks(userLeaving, next, false);
if (mResumedActivity != null) { // 不进入
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Pausing " + mResumedActivity);
pausing |= startPausingLocked(userLeaving, false, next, false);
}
if (pausing && !resumeWhilePausing) {
if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG_STATES,
"resumeTopActivityLocked: Skip resume: need to start pausing");
// At this point we want to put the upcoming activity's process
// at the top of the LRU list, since we know we will be needing it
// very soon and it would be a waste to let it get killed if it
// happens to be sitting towards the end.
if (next.attachedToProcess()) {
next.app.updateProcessInfo(false /* updateServiceConnectionActivities */,
true /* activityChange */, false /* updateOomAdj */);
}
if (lastResumed != null) { // 进入这个分支
lastResumed.setWillCloseOrEnterPip(true);
}
// 返回
return true;
}
// ......
return true;
}
接着开始执行 pauseBackStacks 方法, pause 前一个 Activity。
java
// services/core/java/com/android/server/wm/ActivityDisplay.java
boolean pauseBackStacks(boolean userLeaving, ActivityRecord resuming, boolean dontWait) {
boolean someActivityPaused = false;
for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = mStacks.get(stackNdx);
final ActivityRecord resumedActivity = stack.getResumedActivity();
if (resumedActivity != null
&& (stack.getVisibility(resuming) != STACK_VISIBILITY_VISIBLE
|| !stack.isFocusable())) {
if (DEBUG_STATES) Slog.d(TAG_STATES, "pauseBackStacks: stack=" + stack +
" mResumedActivity=" + resumedActivity);
someActivityPaused |= stack.startPausingLocked(userLeaving, false, resuming,
dontWait);
}
}
return someActivityPaused;
}
pauseBackStacks 的任务就是通过循环找到栈顶 Activity 是 resumed 状态且非 Focusable 的 ActivityStack,然后调用 ActivityStack 的 startPausingLocked 方法:
我们假定的情景下,这里的 ActivityStack 就是 Launcher App 所在的 ActivityStack
java
// services/core/java/com/android/server/wm/ActivityStack.java
final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
ActivityRecord resuming, boolean pauseImmediately) {
if (mPausingActivity != null) { // 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);
}
}
// mResumedActivity 就是 Launcher Activity
ActivityRecord prev = mResumedActivity;
if (prev == null) {
if (resuming == null) {
Slog.wtf(TAG, "Trying to pause when nothing is resumed");
mRootActivityContainer.resumeFocusedStacksTopActivities();
}
return false;
}
// resuming 是待启动的 Activity
if (prev == resuming) { // 不进入
Slog.wtf(TAG, "Trying to pause activity that is in process of being resumed");
return false;
}
if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSING: " + prev);
else if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Start pausing: " + prev);
mPausingActivity = prev; // Laucher
mLastPausedActivity = prev;
// null
mLastNoHistoryActivity = (prev.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
|| (prev.info.flags & ActivityInfo.FLAG_NO_HISTORY) != 0 ? prev : null;
// 设置状态,会发起 Binder RPC 调用到 app 通知状态改变,不是重点
prev.setState(PAUSING, "startPausingLocked");
// 记录一个时间值,表示目标 Activity 开始 active 了
prev.getTaskRecord().touchActiveTime();
clearLaunchTime(prev);
mService.updateCpuStats();
if (prev.attachedToProcess()) { // 进入分支
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
try {
EventLogTags.writeAmPauseActivity(prev.mUserId, System.identityHashCode(prev),
prev.shortComponentName, "userLeaving=" + userLeaving);
// 走这里,发起 Binder RPC 调用,通知 App 执行 onPause
mService.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;
mLastNoHistoryActivity = null;
}
}
// ......
}
接着调用 mService.getLifecycleManager().scheduleTransaction
向 App 端发起 Binder RPC 调用:
java
// /frameworks/base/core/java/android/app/servertransaction/ClientTransaction.java
/**
* 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);
}
接着调用重载 scheduleTransaction:
java
// /frameworks/base/core/java/android/app/servertransaction/ClientTransaction.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:
java
// /frameworks/base/core/java/android/app/servertransaction/ClientTransaction.java
/** Target client. */
private IApplicationThread mClient;
/**
* Schedule the transaction after it was initialized. It will be send to client and all its
* individual parts will be applied in the following sequence:
* 1. The client calls {@link #preExecute(ClientTransactionHandler)}, which triggers all work
* that needs to be done before actually scheduling the transaction for callbacks and
* lifecycle state request.
* 2. The transaction message is scheduled.
* 3. The client calls {@link TransactionExecutor#execute(ClientTransaction)}, which executes
* all callbacks and necessary lifecycle transitions.
*/
public void schedule() throws RemoteException {
mClient.scheduleTransaction(this);
}
层层调用到 IApplicationThread 的 scheduleTransaction 方法,这是一个 Binder RPC 调用:
目前只远程调用 App 端的 scheduleTransaction 方法,pause 前一个 Activity,scheduleTransaction 方法是 oneway 的,所以很可能前一个 Activity 还没有 onPause, 该方法就返回了
它会远程调用到 Activity 端:
java
// /frameworks/base/core/java/android/app/ActivityThread.java
@Override
public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
ActivityThread.this.scheduleTransaction(transaction);
}
/** Prepare and schedule transaction for execution. */
void scheduleTransaction(ClientTransaction transaction) {
transaction.preExecute(this);
sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
}
这里会发送一个 Message,ActivityThread 中的 Handler 中会处理到这个 Message:
java
// /frameworks/base/core/java/android/app/ActivityThread.java
public void handleMessage(Message msg) {
case EXECUTE_TRANSACTION:
// 从 Message 中取出消息
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;
}
- 从 Message 中取出消息
- 执行消息
接着我们来看执行消息的过程:
java
// /frameworks/base/core/java/android/app/servertransaction/TransactionExecutor.java
public void execute(ClientTransaction transaction) {
if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "Start resolving transaction");
// ......
// 执行回调
executeCallbacks(transaction);
// 执行生命周期
executeLifecycleState(transaction);
mPendingActions.clear();
if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "End resolving transaction");
}
接着调用 executeLifecycleState
来执行生命周期:
java
// /frameworks/base/core/java/android/app/servertransaction/TransactionExecutor.java
/** Transition to the final state if requested by the transaction. */
private void executeLifecycleState(ClientTransaction transaction) {
// 拿到 ActivityLifecycleItem,这里是子类 PauseActivityItem
final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();
// ......
// token 是一个索引值
// 通过 token 可以拿到 ActivityClientRecord,这个对象是 App 端的,用于描述描述一个 Activity
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);
}
接着执行 PauseActivityItem 的 execute:
java
// /frameworks/base/core/java/android/app/servertransaction/PauseActivityItem.java
@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);
}
client 的具体类型是 ActivityThread 接着执行到 ActivityThread 的 handlePauseActivity 方法:
java
// /frameworks/base/core/java/android/app/ActivityThread.java
@Override
public void handlePauseActivity(IBinder token, boolean finished, boolean userLeaving,
int configChanges, PendingTransactionActions pendingActions, String reason) {
ActivityClientRecord r = mActivities.get(token);
if (r != null) {
if (userLeaving) { // 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;
}
}
接着调用 performPauseActivity:
java
// /frameworks/base/core/java/android/app/ActivityThread.java
/**
* Pause the activity.
* @return Saved instance state for pre-Honeycomb apps if it was saved, {@code null} otherwise.
*/
private Bundle performPauseActivity(ActivityClientRecord r, boolean finished, String reason,
PendingTransactionActions pendingActions) {
//......
// 关注点
performPauseActivityIfNeeded(r, reason);
//......
}
接着调用 performPauseActivityIfNeeded
:
java
// /frameworks/base/core/java/android/app/ActivityThread.java
private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) {
// ......
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);
}
接着会调用 Activity 的 callActivityOnPause:
java
// /frameworks/base/core/java/android/app/Instrumentation.java
/**
* Perform calling of an activity's {@link Activity#onPause} method. The
* default implementation simply calls through to that method.
*
* @param activity The activity being paused.
*/
public void callActivityOnPause(Activity activity) {
activity.performPause();
}
接着执行 Activity 的 performPause 方法:
java
// /frameworks/base/core/java/android/app/Activity.java
final void performPause() {
dispatchActivityPrePaused();
mDoReportFullyDrawn = false;
mFragments.dispatchPause();
mCalled = false;
onPause();
writeEventLog(LOG_AM_ON_PAUSE_CALLED, "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();
}
在这里就会执行到 Activity 的 onPause 生命周期方法。
生命周期执行完后,接下来回到之前的 executeLifecycleState 方法中:
java
/** Transition to the final state if requested by the transaction. */
private void executeLifecycleState(ClientTransaction transaction) {
// 拿到 ActivityLifecycleItem,这里是子类 PauseActivityItem
final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();
// ......
// 执行生命周期
lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
}
在调用 execute
方法,执行完 onPause 生命周期方法后,接着会调用到 lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
java
@Override
public void postExecute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
if (mDontReport) {
return;
}
try {
// TODO(lifecycler): Use interface callback instead of AMS.
ActivityTaskManager.getService().activityPaused(token);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
在这里,会远程调用到 atms 的 activityPaused 方法。这部分内容我们就留在下一节在分析了。