當前Activity的onPause執行完後,呼叫Paused介面

alpta發表於2021-04-21

前言

在前文中已經講到.

  1. Launcher拉起新的Activity,並在ATMS中執行pause Activity的操作,以及當前Activity執行Pause的流程.
  2. 在當前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,那麼還要呼叫mRootWindowContainerensureActivitiesVisible.

這裡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.

相關文章