ATMS中去pause Activity A.

alpta發表於2021-04-09

上文寫完之後,感覺這個部分寫的還是不清晰,本文繼續補充一下.
首先還是看堆疊.

obtain:78, PauseActivityItem (android.app.servertransaction)
startPausingLocked:1110, ActivityStack (com.android.server.wm)
pauseBackStacks:1200, TaskDisplayArea (com.android.server.wm)
resumeTopActivityInnerLocked:1662, ActivityStack (com.android.server.wm)
resumeTopActivityUncheckedLocked:1511, ActivityStack (com.android.server.wm)
resumeFocusedStacksTopActivities:2299, RootWindowContainer (com.android.server.wm)
startActivityInner:1731, ActivityStarter (com.android.server.wm)
startActivityUnchecked:1521, ActivityStarter (com.android.server.wm)
executeRequest:1186, ActivityStarter (com.android.server.wm)
execute:669, ActivityStarter (com.android.server.wm)
startActivityAsUser:1100, ActivityTaskManagerService (com.android.server.wm)
startActivityAsUser:1072, ActivityTaskManagerService (com.android.server.wm)
startActivity:1047, ActivityTaskManagerService (com.android.server.wm)

我們一步步分析一下.

startActivity:1047, ActivityTaskManagerService (com.android.server.wm)

    public final int startActivity(IApplicationThread caller, String callingPackage,
            String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
            String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
            Bundle bOptions) {
        return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
                resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions,
                UserHandle.getCallingUserId());
    }

簡單的轉發而已

startActivityAsUser:1072, ActivityTaskManagerService

private int startActivityAsUser(IApplicationThread caller, String callingPackage,
            @Nullable String callingFeatureId, Intent intent, String resolvedType,
            IBinder resultTo, String resultWho, int requestCode, int startFlags,
            ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) {
        ...
        // TODO: Switch to user app stacks here.
        return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
                .setCaller(caller)
                .setCallingPackage(callingPackage)
                .setCallingFeatureId(callingFeatureId)
                .setResolvedType(resolvedType)
                .setResultTo(resultTo)
                .setResultWho(resultWho)
                .setRequestCode(requestCode)
                .setStartFlags(startFlags)
                .setProfilerInfo(profilerInfo)
                .setActivityOptions(bOptions)
                .setUserId(userId)
                .execute();
    }
  1. getActivityStartController() 獲取了ATMS的mActivityStartController,該物件在ATMS的initialize中建立.
  2. obtainStarter(intent, "startActivityAsUser") :獲取一個ActivityStarter物件.
  3. set*: 類似於Builder模式,給ActivityStarter的相關變數賦值.
  4. execute() :執行ActivityStarter

execute:669, ActivityStarter

int execute() {
        try { ...
            if (mRequest.activityInfo == null) {
                mRequest.resolveActivity(mSupervisor);
            }

            int res;
            synchronized (mService.mGlobalLock) {
                final boolean globalConfigWillChange = mRequest.globalConfig != null
                        && mService.getGlobalConfiguration().diff(mRequest.globalConfig) != 0;
                final ActivityStack stack = mRootWindowContainer.getTopDisplayFocusedStack();
                if (stack != null) {
                    stack.mConfigWillChange = globalConfigWillChange;
                }
                if (DEBUG_CONFIGURATION) {
                    Slog.v(TAG_CONFIGURATION, "Starting activity when config will change = "
                            + globalConfigWillChange);
                }

                final long origId = Binder.clearCallingIdentity();

                res = resolveToHeavyWeightSwitcherIfNeeded();
                if (res != START_SUCCESS) {
                    return res;
                }
                res = executeRequest(mRequest);

                Binder.restoreCallingIdentity(origId);

                if (globalConfigWillChange) {
                    // If the caller also wants to switch to a new configuration, do so now.
                    // This allows a clean switch, as we are waiting for the current activity
                    // to pause (so we will not destroy it), and have not yet started the
                    // next activity.
                    mService.mAmInternal.enforceCallingPermission(
                            android.Manifest.permission.CHANGE_CONFIGURATION,
                            "updateConfiguration()");
                    if (stack != null) {
                        stack.mConfigWillChange = false;
                    }
                    if (DEBUG_CONFIGURATION) {
                        Slog.v(TAG_CONFIGURATION,
                                "Updating to new configuration after starting activity.");
                    }
                    mService.updateConfigurationLocked(mRequest.globalConfig, null, false);
                }

                // Notify ActivityMetricsLogger that the activity has launched.
                // ActivityMetricsLogger will then wait for the windows to be drawn and populate
                // WaitResult.
                mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(launchingState, res,
                        mLastStartActivityRecord);
                return getExternalResult(mRequest.waitResult == null ? res
                        : waitForResult(res, mLastStartActivityRecord));
            }
        } finally {
            onExecutionComplete();
        }
    }
  1. 如果mRequest.activityInfo為空,就需要呼叫mRequest.resolveActivity(mSupervisor);去獲取.
  2. 檢視config是否有變更,普通啟動一般沒有,先跳過.
  3. resolveToHeavyWeightSwitcherIfNeeded: 暫不清楚是幹嘛的.
  4. res = executeRequest(mRequest); :呼叫executeRequest執行後續操作.

executeRequest:1186, ActivityStarter

private int executeRequest(Request request) {
        ...
        final ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
                callingPackage, callingFeatureId, intent, resolvedType, aInfo,
                mService.getGlobalConfiguration(), resultRecord, resultWho, requestCode,
                request.componentSpecified, voiceSession != null, mSupervisor, checkedOptions,
                sourceRecord);
        mLastStartActivityRecord = r;

        final ActivityStack stack = mRootWindowContainer.getTopDisplayFocusedStack();

        mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,
                request.voiceInteractor, startFlags, true /* doResume */, checkedOptions, inTask,
                restrictedBgActivity, intentGrants);

        if (request.outActivity != null) {
            request.outActivity[0] = mLastStartActivityRecord;
        }

        return mLastStartActivityResult;
    }
  1. 這裡首先做了一系列的判斷,新Activity是否合法,是否可以啟動它.不可以的話則直接返回了.
  2. 新建了一個ActivityRecord物件.它是Activity在ATMS的一個對映.此時Acitivity程式還沒有新建Activity物件,所以此時他們還是不對應的.
  3. 呼叫startActivityUnchecked

startActivityUnchecked:1521, ActivityStarter

private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
                IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                int startFlags, boolean doResume, ActivityOptions options, Task inTask,
                boolean restrictedBgActivity, NeededUriGrants intentGrants) { ...
        try {
            result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,
                    startFlags, doResume, options, inTask, restrictedBgActivity, intentGrants);
        } finally {
            startedActivityStack = handleStartResult(r, result);
        }
...
        return result;
    }

這裡簡單的轉發一下.

startActivityInner:1731, ActivityStarter

int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, Task inTask,
            boolean restrictedBgActivity, NeededUriGrants intentGrants) {
        ...
        computeSourceStack();
        final Task reusedTask = getReusableTask();

        // Compute if there is an existing task that should be used for.
        final Task targetTask = reusedTask != null ? reusedTask : computeTargetTask();
        final boolean newTask = targetTask == null;
        mTargetTask = targetTask;
        // Check if starting activity on given task or on a new task is allowed.
        int startResult = isAllowedToStart(r, newTask, targetTask);
        if (startResult != START_SUCCESS) {
            return startResult;
        }

        final ActivityRecord targetTaskTop = newTask
                ? null : targetTask.getTopNonFinishingActivity();
        if (targetTaskTop != null) {
            // Recycle the target task for this launch.
            startResult = recycleTask(targetTask, targetTaskTop, reusedTask, intentGrants);
            if (startResult != START_SUCCESS) {
                return startResult;
            }
        } else {
            mAddingToTask = true;
        }

        // If the activity being launched is the same as the one currently at the top, then
        // we need to check if it should only be launched once.
        final ActivityStack topStack = mRootWindowContainer.getTopDisplayFocusedStack();
        if (topStack != null) {
            startResult = deliverToCurrentTopIfNeeded(topStack, intentGrants);
            if (startResult != START_SUCCESS) {
                return startResult;
            }
        }

        if (mTargetStack == null) {
            mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, targetTask, mOptions);
        }
        if (newTask) {
            final Task taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
                    ? mSourceRecord.getTask() : null;
            setNewTask(taskToAffiliate);
            if (mService.getLockTaskController().isLockTaskModeViolation(
                    mStartActivity.getTask())) {
                Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
                return START_RETURN_LOCK_TASK_MODE_VIOLATION;
            }
        } else if (mAddingToTask) {
            addOrReparentStartingActivity(targetTask, "adding to task");
        }

        if (!mAvoidMoveToFront && mDoResume) {
            mTargetStack.getStack().moveToFront("reuseOrNewTask", targetTask);
            if (mOptions != null) {
                if (mOptions.getTaskAlwaysOnTop()) {
                    mTargetStack.setAlwaysOnTop(true);
                }
            }
            if (!mTargetStack.isTopStackInDisplayArea() && mService.mInternal.isDreaming()) {
                // Launching underneath dream activity (fullscreen, always-on-top). Run the launch-
                // -behind transition so the Activity gets created and starts in visible state.
                mLaunchTaskBehind = true;
                r.mLaunchTaskBehind = true;
            }
        }

        if (newTask) {
            EventLogTags.writeWmCreateTask(mStartActivity.mUserId,
                    mStartActivity.getTask().mTaskId);
        }

        mTargetStack.mLastPausedActivity = null;

        mTargetStack.startActivityLocked(mStartActivity, topStack.getTopNonFinishingActivity(),
                newTask, mKeepCurTransition, mOptions);
       ...
        return START_SUCCESS;
    }

這裡首先是計算新的Activity啟動所在的堆疊mTargetStack,然後呼叫mTargetStack.startActivityLocked去啟動Activity.

  1. final Task reusedTask = getReusableTask(); 首先檢視現有的任務中是否有可以重複使用的任務.
  2. 如果沒有找到reusedTask,那麼呼叫computeTargetTask 看看能否找到一個task存放這個Activity.如果都不存在的話,那麼就要新建一個Task了.
  3. 我們是從Launcher新啟動一個Activity,並且這個Activity沒有啟動過.一般情況下這裡就會新建一個Task,並且新建一個Stack.並把當前待啟動的ActivityRecord物件放到這個Stack頂.

resumeFocusedStacksTopActivities:2299, RootWindowContainer

 boolean resumeFocusedStacksTopActivities(
            ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
...
        boolean result = false;
        if (targetStack != null && (targetStack.isTopStackInDisplayArea()
                || getTopDisplayFocusedStack() == targetStack)) {
            result = targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
        }
...
}

這裡也是很簡單的就轉給相應的Stack去處理.

resumeTopActivityUncheckedLocked:1511, ActivityStack

boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
   ...
        boolean result = false;
        try {
            // Protect against recursion.
            mInResumeTopActivity = true;
            result = resumeTopActivityInnerLocked(prev, options);
...
        } finally {
            mInResumeTopActivity = false;
        }
...
    }

轉發給Lock函式處理.

resumeTopActivityInnerLocked:1666, ActivityStack

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
      ...
        boolean pausing = taskDisplayArea.pauseBackStacks(userLeaving, next);
        if (mResumedActivity != null) {
            if (DEBUG_STATES) Slog.d(TAG_STATES,
                    "resumeTopActivityLocked: Pausing " + mResumedActivity);
            pausing |= startPausingLocked(userLeaving, false /* uiSleeping */, next);
        }
  1. 前面省略的邏輯中有一部分是判斷當前是否有Acitivity正在執行pause操作,是的話這裡就直接返回了.
  2. 如果不是的話,則先pause當前顯示區域的後臺堆疊中的resumed狀態的Activity,然後pause當前棧的resumed Activity.

startPausingLocked:1110, ActivityStack

final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
            ActivityRecord resuming) {
...
         if (prev.attachedToProcess()) {
            if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
            try {
                EventLogTags.writeWmPauseActivity(prev.mUserId, System.identityHashCode(prev),
                        prev.shortComponentName, "userLeaving=" + userLeaving);

                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;
                mLastNoHistoryActivity = null;
            }
        } else {
            mPausingActivity = null;
            mLastPausedActivity = null;
            mLastNoHistoryActivity = null;
        }
}

這裡的prev對應的就是當前棧中的mResumedActivity,如果當前它還是attach到程式上的,那麼這裡就呼叫scheduleTransaction給他傳遞了一個pause操作

相關文章