前言
在前文中已經講到.
- Launcher拉起新的Activity,並在ATMS中執行pause Activity的操作,以及當前Activity執行Pause的流程.
- 在當前Activity執行pause時同步執行拉起新程式操作.
本文主要講當前Activity已經執行完Pause操作,呼叫ATMS的activityPaused介面,告知當前Activity已經暫停成功了的流程.
詳細流程分析
在PauseActivityItem
執行postExecute
時,就會呼叫ActivityTaskManager.getService().activityPaused(token);
這個方法通過binder呼叫到ATMS的activityPaused.
activityPaused:1843, ActivityTaskManagerService
public final void activityPaused(IBinder token) {
synchronized (mGlobalLock) {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "activityPaused");
final ActivityRecord r = ActivityRecord.forTokenLocked(token);
if (r != null) {
r.activityPaused(false);
}
}
Binder.restoreCallingIdentity(origId);
}
這裡首先通過token去獲取了當前Pause的Activity在ATMS中對應的ActivityRecord例項,然後呼叫
ActivityRecord的activityPaused.
todo:Activity,ActivityRecord,token,stack,task之間的關係.
activityPaused:4930, ActivityRecord
void activityPaused(boolean timeout) {
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE,
"Activity paused: token=" + appToken + ", timeout=" + timeout);
final ActivityStack stack = getStack();
首先查詢當前的ActivityRecord對應的ActivityStack
if (stack != null) {
removePauseTimeout();
if (stack.mPausingActivity == this) {
if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSED: " + this
+ (timeout ? " (due to timeout)" : " (pause complete)"));
mAtmService.deferWindowLayout();
try {
stack.completePauseLocked(true /* resumeNext */, null /* resumingActivity */);
} finally {
mAtmService.continueWindowLayout();
}
return;
如果stack正在pausing的Activity是當前Activity,那麼呼叫stack.completePauseLocked
去resume下一個待resume的activity.
} else {
if (isState(PAUSING)) {
setState(PAUSED, "activityPausedLocked");
if (finishing) {
if (DEBUG_PAUSE) Slog.v(TAG,
"Executing finish of failed to pause activity: " + this);
completeFinishing("activityPausedLocked");
}
}
}
如果當前在pausing的activity不是當前的這個Activity.那麼做一些狀態的處理.(假設Activity a pause但是超時了,那麼在超時的時候就會呼叫paused操作.此時又把當前resume的Activity pause,而 a Activity有回撥了activityPaused
介面就會進入這個分支.)
}
mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
}
如果當前Activity的堆疊為空,或者當前pausing Activity不是當前這個Activity,那麼還要呼叫mRootWindowContainer
的ensureActivitiesVisible
.
這裡pausing Activity就是當前這個Activity,所以執行stack.completePauseLocked
completePauseLocked:1166, ActivityStack
void completePauseLocked(boolean resumeNext, ActivityRecord resuming) {
ActivityRecord prev = mPausingActivity;
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Complete pause: " + prev);
if (prev != null) {
prev.setWillCloseOrEnterPip(false);
final boolean wasStopping = prev.isState(STOPPING);
prev.setState(PAUSED, "completePausedLocked");
if (prev.finishing) {
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Executing finish of activity: " + prev);
prev = prev.completeFinishing("completePausedLocked");
} else if (prev.hasProcess()) {
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueue pending stop if needed: " + prev
+ " wasStopping=" + wasStopping
+ " visibleRequested=" + prev.mVisibleRequested);
if (prev.deferRelaunchUntilPaused) {
// Complete the deferred relaunch that was waiting for pause to complete.
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Re-launching after pause: " + 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 {
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "App died during pause, not stopping: " + 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;
}
先獲取當前Activity棧中待pause的Activity,執行一些Activity pause後的收尾工作.
if (resumeNext) {
final ActivityStack topStack = mRootWindowContainer.getTopDisplayFocusedStack();
if (topStack != null && !topStack.shouldSleepOrShutDownActivities()) {
mRootWindowContainer.resumeFocusedStacksTopActivities(topStack, prev, null);
} else {
checkReadyForSleep();
final ActivityRecord top = topStack != null ? topStack.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 stack is not the just paused
// activity, we need to go ahead and resume it to ensure we complete an
// in-flight app switch.
mRootWindowContainer.resumeFocusedStacksTopActivities();
}
}
}
如果需要resume 下一個activity,那麼呼叫mRootWindowContainer.resumeFocusedStacksTopActivities
去resume它.
上面兩個不同引數的resumeFocusedStacksTopActivities
方法的區別在於第一種是確定要拉起哪個堆疊中的Activity,另一個是要從所有的顯示區域去找一個需要顯示的堆疊,如果找不到的話則拉起Launcher.