Android S从桌面点击图标启动APP流程 (二)

 系列文章

Android S从桌面点击图标启动APP流程 (一)
Android S从桌面点击图标启动APP流程 (二)

Android S从桌面点击图标启动APP流程 (三)

Android S从桌面点击图标启动APP流程 (四)

Android 12的源码链接:

Android 12 Aospicon-default.png?t=N7T8http://aospxref.com/android-12.0.0_r3/

43eeb6708a334c8da350b08bee444170.jpg

16. ActivityStarter#startActivityUnchecked

frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java

*在完成大部分初步检查并确认调用方拥有执行此操作的必要权限时启动activity 。此处还可确保在启动不成功时删除启动activity 。
   
    private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,int startFlags, boolean doResume, ActivityOptions options, Task inTask, boolean restrictedBgActivity, NeededUriGrants intentGrants) {
        int result = START_CANCELED;
        final Task startedActivityRootTask;

立即创建一个过渡,以记录在 startActivityInner 中执行的操作的原始意图。否则,startActivityInner 中的逻辑可能会根据子操作启动不同的转换。只在这里创建(并推迟requestStart),因为startActivityInside可能会中止。
        final Transition newTransition = (!mService.getTransitionController().isCollecting() && mService.getTransitionController().getTransitionPlayer() != null) ? mService.getTransitionController().createTransition(TRANSIT_OPEN) : null;
        IRemoteTransition remoteTransition = r.takeRemoteTransition();
        if (newTransition != null && remoteTransition != null) {
            newTransition.setRemoteTransition(remoteTransition);
        }
        mService.getTransitionController().collect(r);
​
        try {
//延迟绘制
            mService.deferWindowLayout();
            Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner");
//start activity
            result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,startFlags, doResume, options, inTask, restrictedBgActivity, intentGrants);
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
            startedActivityRootTask = handleStartResult(r, result);
//continue绘制
            mService.continueWindowLayout();

10-08 23:28:37.882  1601  1817 I ActivityTaskManager: continueWindowLayout reason=0
frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
    /** @see WindowSurfacePlacer#continueLayout */
    void continueWindowLayout() {
        mWindowManager.mWindowPlacerLocked.continueLayout(mLayoutReasons != 0);
        if (DEBUG_ALL && !mWindowManager.mWindowPlacerLocked.isLayoutDeferred()) {
            Slog.i(TAG, "continueWindowLayout reason=" + mLayoutReasons);
        }
    }
    /** @see WindowSurfacePlacer#deferLayout */
    void deferWindowLayout() {
        if (!mWindowManager.mWindowPlacerLocked.isLayoutDeferred()) {
            // Reset the reasons at the first entrance because we only care about the changes in the deferred scope.
            mLayoutReasons = 0;
        }
        mWindowManager.mWindowPlacerLocked.deferLayout();
    }

           mSupervisor.mUserLeaving = false;

            // Transition housekeeping
            if (!ActivityManager.isStartResultSuccessful(result)) {
                if (newTransition != null) {
                    newTransition.abort();
                }
            } else {
                if (!mAvoidMoveToFront && mDoResume
                        && mRootWindowContainer.hasVisibleWindowAboveButDoesNotOwnNotificationShade( r.launchedFromUid)) {
如果正在启动的activity 的 UID 在通知栏的顶部有一个可见窗口,并且它启动的activity 将位于前面,我们应该将底页移开,以便用户可以看到它。我们希望避免在未移动到前面的后台任务之上启动activity 的情况。
                    StatusBarManagerInternal statusBar = mService.getStatusBarManagerInternal();
                    if (statusBar != null) {
                   // This results in a async call since the interface is one-way
                        这会导致异步调用,因为接口是单向的
                        statusBar.collapsePanels();
                    }
                }
                if (result == START_SUCCESS || result == START_TASK_TO_FRONT) {
                    // The activity is started new rather than just brought forward, so record it as an existence change.
activity 是新开始的,而不仅仅是提前开始的,因此请将其记录为存在更改。
                    mService.getTransitionController().collectExistenceChange(r);
                }
                if (newTransition != null) {
                    mService.getTransitionController().requestStartTransition(newTransition,
                            mTargetTask, remoteTransition);
                } else {
              // Make the collecting transition wait until this request is ready.
              使ollecting transition等到此请求准备就绪。
                    mService.getTransitionController().setReady(false);
                }
            }
        }

        postStartActivityProcessing(r, result, startedActivityRootTask);

        return result;
    }

  17. ActivityStarter#startActivityInner

frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java

启动activity并确定该activity是应添加到现有任务的顶部,还是应将新意向交付到现有activity。还将activity task操作到请求的或有效的根任务/显示上。
    @VisibleForTesting
    int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,int startFlags, boolean doResume, ActivityOptions options, Task inTask, boolean restrictedBgActivity, NeededUriGrants intentGrants) {
        setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,voiceInteractor, restrictedBgActivity);
        computeLaunchingTaskFlags();
        computeSourceRootTask();
        mIntent.setFlags(mLaunchFlags);
        final Task reusedTask = getReusableTask();

        setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,  voiceInteractor, restrictedBgActivity);
//计算启动的Flags
        computeLaunchingTaskFlags();

        computeSourceRootTask();

        mIntent.setFlags(mLaunchFlags);

        final Task reusedTask = getReusableTask();

        // If requested, freeze the task list
        if (mOptions != null && mOptions.freezeRecentTasksReordering()
                && mSupervisor.mRecentTasks.isCallerRecents(r.launchedFromUid)
                && !mSupervisor.mRecentTasks.isFreezeTaskListReorderingSet()) {
            mFrozeTaskList = true;
            mSupervisor.mRecentTasks.setFreezeTaskListReordering();
        }

        // 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;
        computeLaunchParams(r, sourceRecord, 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 Task topRootTask = mPreferredTaskDisplayArea.getFocusedRootTask();
        if (topRootTask != null) {
            startResult = deliverToCurrentTopIfNeeded(topRootTask, intentGrants);
            if (startResult != START_SUCCESS) {
                return startResult;
            }
        }

        if (mTargetRootTask == null) {
            mTargetRootTask = getLaunchRootTask(mStartActivity, mLaunchFlags, targetTask, mOptions);
        }
        if (newTask) {
            final Task taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)  ? mSourceRecord.getTask() : null;
            setNewTask(taskToAffiliate);
        } else if (mAddingToTask) {
            addOrReparentStartingActivity(targetTask, "adding to task");
        }

        if (!mAvoidMoveToFront && mDoResume) {
            mTargetRootTask.getRootTask().moveToFront("reuseOrNewTask", targetTask);
            if (mOptions != null) {
                if (mOptions.getTaskAlwaysOnTop()) {
                    mTargetRootTask.setAlwaysOnTop(true);
                }
            }
            if (!mTargetRootTask.isTopRootTaskInDisplayArea() && 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;
            }
        }

        mService.mUgmInternal.grantUriPermissionUncheckedFromIntent(intentGrants,
                mStartActivity.getUriPermissionsLocked());
        if (mStartActivity.resultTo != null && mStartActivity.resultTo.info != null) {
            // we need to resolve resultTo to a uid as grantImplicitAccess deals explicitly in UIDs
            final PackageManagerInternal pmInternal =
                    mService.getPackageManagerInternalLocked();
            final int resultToUid = pmInternal.getPackageUid(
                    mStartActivity.resultTo.info.packageName, 0 /* flags */,
                    mStartActivity.mUserId);
            pmInternal.grantImplicitAccess(mStartActivity.mUserId, mIntent,
                    UserHandle.getAppId(mStartActivity.info.applicationInfo.uid) /*recipient*/, resultToUid /*visible*/, true /*direct*/);
        }
        if (newTask) {
            EventLogTags.writeWmCreateTask(mStartActivity.mUserId,
                    mStartActivity.getTask().mTaskId);
        }
        mStartActivity.logStartActivity(
                EventLogTags.WM_CREATE_ACTIVITY, mStartActivity.getTask());

        mTargetRootTask.mLastPausedActivity = null;
​

        mRootWindowContainer.startPowerModeLaunchIfNeeded(
                false /* forceSend */, mStartActivity);
        mTargetRootTask.startActivityLocked(mStartActivity, topRootTask != null ? topRootTask.getTopNonFinishingActivity() : null, newTask,mKeepCurTransition, mOptions, sourceRecord);
10-11 05:23:15.891  1562  1782 V ActivityTaskManager: Prepare open transition: starting ActivityRecord{be18a2 u0 com.android.calendar/.AllInOneActivity t8}
        if (mDoResume) {
            final ActivityRecord topTaskActivity =
                    mStartActivity.getTask().topRunningActivityLocked();
            if (!mTargetRootTask.isTopActivityFocusable()
                    || (topTaskActivity != null && topTaskActivity.isTaskOverlay()
                    && mStartActivity != topTaskActivity)) {
                  mTargetRootTask.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */, !PRESERVE_WINDOWS);
                  mTargetRootTask.mDisplayContent.executeAppTransition();
            } else {
                  if (mTargetRootTask.isTopActivityFocusable()
 && !mRootWindowContainer.isTopDisplayFocusedRootTask(mTargetRootTask)) {
                    mTargetRootTask.moveToFront("startActivityInner");
                  }
               mRootWindowContainer.resumeFocusedTasksTopActivities(
mTargetRootTask, mStartActivity, mOptions, mTransientLaunch);
10-11 05:23:15.894  1562  1782 V ActivityTaskManager: Resuming ActivityRecord{be18a2 u0 com.android.calendar/.AllInOneActivity t8}

10-11 05:23:15.895  1562  1782 D ActivityTaskManager: setResumedActivity taskFrag:Task{3aa0954 #6 type=home I=com.android.launcher3/.uioverrides.QuickstepLauncher U=0 rootTaskId=1 visible=true visibleRequested=true mode=fullscreen translucent=false sz=1} + from: ActivityRecord{b1a7043 u0 com.android.launcher3/.uioverrides.QuickstepLauncher t6} to:null reason:startPausingLocked - onActivityStateChanged
            }
        }
        mRootWindowContainer.updateUserRootTask(mStartActivity.mUserId, mTargetRootTask);
        //活动开始时立即更新近期任务列表
        // Update the recent tasks list immediately when the activity starts
        mSupervisor.mRecentTasks.add(mStartActivity.getTask());
10-11 05:23:15.896  1562  1782 D ActivityTaskManager: add: task=Task{126146d #8 type=standard A=10075:android.task.calendar U=0 visible=true visibleRequested=false mode=fullscreen translucent=true sz=1}
10-11 05:23:15.897  1562  1782 D ActivityTaskManager: addRecent: trimming tasks for Task{126146d #8 type=standard A=10075:android.task.calendar U=0 visible=true visibleRequested=false mode=fullscreen translucent=true sz=1}
10-11 05:23:15.897  1562  1782 D ActivityTaskManager: addRecent: adding Task{126146d #8 type=standard A=10075:android.task.calendar U=0 visible=true visibleRequested=false mode=fullscreen translucent=true sz=1}

        mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(),
             mPreferredWindowingMode, mPreferredTaskDisplayArea, mTargetRootTask);

        return START_SUCCESS;
    }
​

18. ActivityStarter#startActivityLocked

    void startActivityLocked(ActivityRecord r, @Nullable ActivityRecord focusedTopActivity,
            boolean newTask, boolean keepCurTransition, ActivityOptions options,
            @Nullable ActivityRecord sourceRecord) {
        Task rTask = r.getTask();
        final boolean allowMoveToFront = options == null || !options.getAvoidMoveToFront();
        final boolean isOrhasTask = rTask == this || hasChild(rTask);
        // mLaunchTaskBehind tasks get placed at the back of the task stack.
        if (!r.mLaunchTaskBehind && allowMoveToFront && (!isOrhasTask || newTask)) {
            // Last activity in task had been removed or ActivityManagerService is reusing task. Insert or replace. Might not even be in.

任务中的最后一个activity 已被删除,或者activity 管理器服务正在重用task。插入或替换。甚至可能不在。
            positionChildAtTop(rTask);
        }
        Task task = null;
        if (!newTask && isOrhasTask) {
            // Starting activity cannot be occluding activity, otherwise starting window could be remove immediately without transferring to starting activity.

Starting activity不能遮挡活动,否则可以立即删除Starting activity,而不会转移到启动activity。
            final ActivityRecord occludingActivity = getOccludingActivityAbove(r);
            if (occludingActivity != null) {
                // Here it is!  Now, if this is not yet visible (occluded by another task) to the user, then just add it without starting; it will get started when the user navigates back to it.

 现在,如果这对用户还不可见(被另一个任务遮挡),那么只需添加它而不启动;当用户导航回到它时,它将开始。
                ProtoLog.i(WM_DEBUG_ADD_REMOVE, "Adding activity %s to task %s "
                                + "callers: %s", r, task,
                        new RuntimeException("here").fillInStackTrace());
                rTask.positionChildAtTop(r);
                ActivityOptions.abort(options);
                return;
            }
        }

        // Place a new activity at top of root task, so it is next to interact with the user. If we are not placing the new activity frontmost, we do not want to deliver the onUserLeaving callback to the actual frontmost activity

将新activity放在根任务的顶部,以便它接下来与用户交互。如果我们没有将新activity放在最前面,我们不希望将 onUserLeave 回调传递到实际的最前面的activity
        final Task activityTask = r.getTask();
        if (task == activityTask && mChildren.indexOf(task) != (getChildCount() - 1)) {
            mTaskSupervisor.mUserLeaving = false;
            if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
                    "startActivity() behind front, mUserLeaving=false");
        }

        task = activityTask;

        // Slot the activity into the history root task and proceed
        ProtoLog.i(WM_DEBUG_ADD_REMOVE, "Adding activity %s to task %s "
                        + "callers: %s", r, task, new RuntimeException("here").fillInStackTrace());
        task.positionChildAtTop(r);

//如果 {@code allowMoveToFront} 为 false,则不需要过渡动画和启动窗口,因为活动将不可见。
        if ((!isHomeOrRecentsRootTask() || hasActivity()) && allowMoveToFront) {
            final DisplayContent dc = mDisplayContent;
            if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
                    "Prepare open transition: starting " + r);
10-11 05:23:15.891  1562  1782 V ActivityTaskManager: Prepare open transition: starting ActivityRecord{be18a2 u0 com.android.calendar/.AllInOneActivity t8}
            // TODO(shell-transitions): record NO_ANIMATION flag somewhere.
            if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
                dc.prepareAppTransition(TRANSIT_NONE);
                mTaskSupervisor.mNoAnimActivities.add(r);
            } else {
                int transit = TRANSIT_OLD_ACTIVITY_OPEN;
                if (newTask) {
                    if (r.mLaunchTaskBehind) {
                        transit = TRANSIT_OLD_TASK_OPEN_BEHIND;
                    } else {
                        // 如果正在启动新任务,则将现有的顶部activity标记为支持画中画,同时仅在启动activity不被视为当前activity之上的叠加层(例如,不是全屏或助手)时暂停
                        if (canEnterPipOnTaskSwitch(focusedTopActivity,
                                null /* toFrontTask */, r, options)) {
                            focusedTopActivity.supportsEnterPipOnTaskSwitch = true;
                        }
                        transit = TRANSIT_OLD_TASK_OPEN;
                    }
                }
                dc.prepareAppTransition(TRANSIT_OPEN);
                mTaskSupervisor.mNoAnimActivities.remove(r);
            }
            boolean doShow = true;
            if (newTask) {
//即使此activity是重新开始的,我们仍然需要重置它,以确保我们应用相关性将任何现有activity从其他任务移动到它。如果调用方已请求重置目标任务,则执行此操作。
                if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
                    resetTaskIfNeeded(r, r);
                    doShow = topRunningNonDelayedActivityLocked(null) == r;
                }
            } else if (options != null && options.getAnimationType()
                    == ActivityOptions.ANIM_SCENE_TRANSITION) {
                doShow = false;
            }
            if (r.mLaunchTaskBehind) {

//不要为 mLaunchTaskBehind 做一个starting window。更重要的是,确保我们告诉 WindowManager r 是可见的,即使它位于根任务的后面。
                r.setVisibility(true);
                ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
                // 继续为此activity执行应用转换,因为不会通过恢复通道触发应用转换。
                mDisplayContent.executeAppTransition();
            } else if (SHOW_APP_STARTING_PREVIEW && doShow) {
                // Figure out if we are transitioning from another activity that is "has the same starting icon" as the next one.  This allows the window manager to keep the previous window it had previously created, if it still had one.
                Task prevTask = r.getTask();
                ActivityRecord prev = prevTask.topActivityWithStartingWindow();
                if (prev != null) {
                    // We don't want to reuse the previous starting preview if: (1) The current activity is in a different task.
                    if (prev.getTask() != prevTask) {
                        prev = null;
                    }
                    // (2) The current activity is already displayed.
                    else if (prev.nowVisible) {
                        prev = null;
                    }
                }

//显示starting window

//showStartingWindow->addStartingWindow->addSplashScreenStartingWindow

                r.showStartingWindow(prev, newTask, isTaskSwitch(r, focusedTopActivity),true /* startActivity */, sourceRecord);

10-11 05:23:15.935  1863  2028 D SplashScreenView: Build android.window.SplashScreenView{6a2eb98 V.E...... ......ID 0,0-0,0}
10-11 05:23:15.935  1863  2028 D SplashScreenView: Icon: view: android.widget.ImageView{6b6cff1 V.ED..... ......I. 0,0-0,0 #10204aa android:id/splashscreen_icon_view} drawable: com.android.wm.shell.startingsurface.SplashscreenIconDrawableFactory$ImmobileIconDrawable@49827d6 size: 640
10-11 05:23:15.935  1863  2028 D SplashScreenView: Branding: view: android.view.View{6705a57 G.ED..... ......I. 0,0-0,0 #10204a9 android:id/splashscreen_branding_view} drawable: null size w: 0 h: 0
            }
        } else {
            // If this is the first activity, don't do any fancy animations, because there is nothing for it to animate on top of.
            ActivityOptions.abort(options);
        }
    }

19. RootWindowContainer#resumeFocusedTasksTopActivities

 frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java

    boolean resumeFocusedTasksTopActivities() {
        return resumeFocusedTasksTopActivities(null, null, null);
    }
----------------------------------------------------------------------------------
    boolean resumeFocusedTasksTopActivities(
            Task targetRootTask, ActivityRecord target, ActivityOptions targetOptions) {
        return resumeFocusedTasksTopActivities(targetRootTask, target, targetOptions, false /* deferPause */);
    }
----------------------------------------------------------------------------------
    boolean resumeFocusedTasksTopActivities(
            Task targetRootTask, ActivityRecord target, ActivityOptions targetOptions, boolean deferPause) { 
       if (!mTaskSupervisor.readyToResume()) {
            return false;
        }

        boolean result = false;
        if (targetRootTask != null && (targetRootTask.isTopRootTaskInDisplayArea()
                || getTopDisplayFocusedRootTask() == targetRootTask)) {
            result = targetRootTask.resumeTopActivityUncheckedLocked(target, targetOptions, deferPause);
        }

        for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
            final DisplayContent display = getChildAt(displayNdx);
            final boolean curResult = result;
            boolean[] resumedOnDisplay = new boolean[1];
            display.forAllRootTasks(rootTask -> {
                final ActivityRecord topRunningActivity = rootTask.topRunningActivity();
                if (!rootTask.isFocusableAndVisible() || topRunningActivity == null) {
                    return;
                }
                if (rootTask == targetRootTask) {
                    resumedOnDisplay[0] |= curResult;
                    return;
                }
                if (rootTask.getDisplayArea().isTopRootTask(rootTask)
                        && topRunningActivity.isState(RESUMED)) {
                    rootTask.executeAppTransition(targetOptions);
                } else {
                    resumedOnDisplay[0] |= topRunningActivity.makeActiveIfNeeded(target);
                }
            });
            result |= resumedOnDisplay[0];
            if (!resumedOnDisplay[0]) {
                final Task focusedRoot = display.getFocusedRootTask();
                if (focusedRoot != null) {
                    result |= focusedRoot.resumeTopActivityUncheckedLocked(target, targetOptions);
                } else if (targetRootTask == null) {
                    result |= resumeHomeActivity(null /* prev */, "no-focusable-task", display.getDefaultTaskDisplayArea());
                }
            }
        }

        return result;
    }

20. RootWindowContainer#resumeTopActivityUncheckedLocked

 frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java

    boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
        return resumeTopActivityUncheckedLocked(prev, options, false /* skipPause */);
    }    
----------------------------------------------------------------------------
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options,
            boolean deferPause) {
        if (mInResumeTopActivity) {
            // Don't even start recursing.
            return false;
        }

        boolean someActivityResumed = false;
        try {
            // Protect against recursion.
            mInResumeTopActivity = true;

            if (isLeafTask()) {
                if (isFocusableAndVisible()) {
//
                    someActivityResumed = resumeTopActivityInnerLocked(prev, options, deferPause);
                }
            } else {
                int idx = mChildren.size() - 1;
                while (idx >= 0) {
                    final Task child = (Task) getChildAt(idx--);
                    if (!child.isTopActivityFocusable()) {
                        continue;
                    }
                    if (child.getVisibility(null /* starting */) != TASK_VISIBILITY_VISIBLE) {
                        break;
                    }

                    someActivityResumed |= child.resumeTopActivityUncheckedLocked(prev, options, deferPause);
                    if (idx >= mChildren.size()) {
                        idx = mChildren.size() - 1;
                    }
                }
            }
            final ActivityRecord next = topRunningActivity(true /* focusableOnly */);
            if (next == null || !next.canTurnScreenOn()) {
                checkReadyForSleep();
            }
        } finally {
            mInResumeTopActivity = false;
        }

        return someActivityResumed;
    }

21. RootWindowContainer#resumeTopActivityInnerLocked

 frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java

    @GuardedBy("mService")
    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options,
            boolean deferPause) {
...

        next代表将要去resume的activity
        ActivityRecord next = topRunningActivity(true /* focusableOnly */);

        final boolean hasRunningActivity = next != null;

        // TODO: Maybe this entire condition can get removed?
        if (hasRunningActivity && !isAttached()) {
            return false;
        }

        mRootWindowContainer.cancelInitializingActivities();

        if (!hasRunningActivity) {//如果将要启动的activity为null
            // There are no activities left in the root task, let's look somewhere else.

            根任务中没有activitiy,让我们看看其他地方。
            return resumeNextFocusableActivityWhenRootTaskIsEmpty(prev, options);
        }

        next.delayedResume = false;
        final TaskDisplayArea taskDisplayArea = getDisplayArea();

        // If the top activity is the resumed one, nothing to do.

       如果top activity是resumed的activity,则无需执行任何操作。
        if (mResumedActivity == next && next.isState(RESUMED)
                && taskDisplayArea.allResumedActivitiesComplete()) {
            //确保我们已执行任何挂起的转换,因为此时应该没有什么可做的。
            executeAppTransition(options);
对于未处于全屏模式的设备(例如自由格式窗口),我们可能仍希望检查其他窗口的可见性是否已更改(例如,将全屏窗口向前移动以覆盖另一个自由格式活动)。
            if (taskDisplayArea.inMultiWindowMode()) {
                taskDisplayArea.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
                        false /* preserveWindows */, true /* notifyClients */);
            }
            ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivityLocked: Top activity "
                    + "resumed %s", next);
            return false;
        }

        if (!next.canResumeByCompat()) {
            return false;
        }

         //如果我们当前正在暂停一个activity,那么在暂停之前不要执行任何操作。
        final boolean allPausedComplete = mRootWindowContainer.allPausedActivitiesComplete();
        if (!allPausedComplete) {
            ProtoLog.v(WM_DEBUG_STATES,
                    "resumeTopActivityLocked: Skip resume: some activity pausing.");

            return false;
        }


     //如果我们在sleeping,并且没有resumed的activity,并且顶级activity暂停,那么这就是我们想要的状态。
        if (mLastPausedActivity == next && shouldSleepOrShutDownActivities()) {
           //确保我们已执行任何挂起的转换,因为此时应该没有什么可做的。
            executeAppTransition(options);
            ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivityLocked: Going to sleep and"
                    + " all paused");
            return false;
        }

//确保拥有此activity的用户已启动。 如果没有,我们将保持原样,因为有人应该将其他用户的activity带到堆栈的顶部。
        if (!mAtmService.mAmInternal.hasStartedUserState(next.mUserId)) {
            Slog.w(TAG, "Skipping resume of top activity " + next
                    + ": user " + next.mUserId + " is stopped");
            return false;
        }

         activity可能正在等待停止,但这不再适合它。
        mTaskSupervisor.mStoppingActivities.remove(next);

        if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next);

10-08 23:28:37.877  1601  1817 V ActivityTaskManager: Resuming ActivityRecord{37cd946 u0 com.example.android.locationattribution/.MainActivity t9}

        mTaskSupervisor.setLaunchSource(next.info.applicationInfo.uid);

        ActivityRecord lastResumed = null;
        final Task lastFocusedRootTask = taskDisplayArea.getLastFocusedRootTask();
        if (lastFocusedRootTask != null && lastFocusedRootTask != getRootTask()) {

那么,我们为什么不在这里使用 prev呢???请参阅有关该方法的参数注释。“上一个”不表示上次resumed的activity。但是,如果最后一个焦点堆栈不为 null,则它执行。
            lastResumed = lastFocusedRootTask.getResumedActivity();
        }

        boolean pausing = !deferPause && taskDisplayArea.pauseBackTasks(next);

        if (mResumedActivity != null) {
            ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivityLocked: Pausing %s", mResumedActivity);
            pausing |= startPausingLocked(false /* uiSleeping */, next,
                    "resumeTopActivityInnerLocked");
        }

...

22. taskDisplayArea#pauseBackTasks

frameworks/base/services/core/java/com/android/server/wm/TaskDisplayArea.java
    boolean pauseBackTasks(ActivityRecord resuming) {
        final int[] someActivityPaused = {0};
        forAllLeafTasks((task) -> {
            final ActivityRecord resumedActivity = task.getResumedActivity();
            if (resumedActivity != null
                    && (task.getVisibility(resuming) != TASK_VISIBILITY_VISIBLE
                    || !task.isTopActivityFocusable())) {
                ProtoLog.d(WM_DEBUG_STATES, "pauseBackTasks: task=%s "
                        + "mResumedActivity=%s", task, resumedActivity);
                if (task.startPausingLocked(false /* uiSleeping*/,
                        resuming, "pauseBackTasks")) {
                    someActivityPaused[0]++;
                }
            }
        }, true /* traverseTopToBottom */);
        return someActivityPaused[0] > 0;
    }

23. Task#startPausingLocked

frameworks/base/services/core/java/com/android/server/wm/Task.java
    final boolean startPausingLocked(boolean uiSleeping, ActivityRecord resuming, String reason) {
        return startPausingLocked(mTaskSupervisor.mUserLeaving, uiSleeping, resuming, reason);
    }

24. Task#startPausingLocked

    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()) {

避免检查睡眠时递归,并在睡眠期间完全暂停。由于activity 将在resume后立即暂停,因此只需让暂停按客户端暂停的activity 顺序完成即可。
                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) {

如果设置了标志RESUME_WHILE_PAUSING,则继续安排暂停上一个activity ,同时仅当上一个activity 无法进入 Pip 时才恢复新的resumed activity 活动,因为我们希望让 Pip 活动有机会在恢复下一个activity 之前进入 Pip。
            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) {//进入PIP
                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);

10-11 05:23:15.895  1562  1782 I wm_pause_activity: [0,186282051,com.android.launcher3/.uioverrides.QuickstepLauncher,userLeaving=true,pauseBackTasks]                           mAtmService.getLifecycleManager().scheduleTransaction(prev.app.getThread(),
prev.appToken, PauseActivityItem.obtain(prev.finishing, userLeaving,  prev.configChangeFlags, pauseImmediately));

                } catch (Exception e) {
...

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值