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

16 篇文章 1 订阅
6 篇文章 0 订阅

 系列文章

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

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

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

Android 12的源码链接:

Android 12 AOSP Searchhttp://aospxref.com/android-12.0.0_r3/

e9b7452272804b48b840e2111d863dd2.jpg

本文重点讲解activity pause完成后通知Server端以及之后的操作。

 35. PauseActivityItem#postExecute

TransactionExecutor#executeCallbacks方法中可以看到,在执行完execute后会执行callback的postExecute,这个callback对应的是PauseActivityItem

frameworks/base/core/java/android/app/servertransaction/TransactionExecutor.java

    public void executeCallbacks(ClientTransaction transaction) {
...
        final int size = callbacks.size();
        for (int i = 0; i < size; ++i) {
            final ClientTransactionItem item = callbacks.get(i);
            if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "Resolving callback: " + item);
            final int postExecutionState = item.getPostExecutionState();
            final int closestPreExecutionState = mHelper.getClosestPreExecutionState(r,
                    item.getPostExecutionState());
            if (closestPreExecutionState != UNDEFINED) {
                cycleToPath(r, closestPreExecutionState, transaction);
            }

            item.execute(mTransactionHandler, token, mPendingActions);
            item.postExecute(mTransactionHandler, token, mPendingActions);
...
frameworks/base/core/java/android/app/servertransaction/PauseActivityItem.java
    @Override
    public void postExecute(ClientTransactionHandler client, IBinder token,
            PendingTransactionActions pendingActions) {
        if (mDontReport) {
            return;
        }
        // TODO(lifecycler): Use interface callback instead of actual implementation.
----通知Server端应用已经pause完成
        ActivityClient.getInstance().activityPaused(token);
    }

​

36. ActivityClient#activityPaused

frameworks/base/core/java/android/app/ActivityClient.java
    /** Reports {@link Activity#onPause()} is done. */
    public void activityPaused(IBinder token) {
        try {
---调用server端activityPaused,通知ams已经paused完成

getActivityClientController如下
            getActivityClientController().activityPaused(token);
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
        }
    }

    private static IActivityClientController getActivityClientController() {
        final IActivityClientController controller = INTERFACE_SINGLETON.mKnownInstance;
        return controller != null ? controller : INTERFACE_SINGLETON.get();
    }

此处也存在一个aidl通信,aidl文件路径为,作用为:

Interface for the callback and request from an activity to system.

frameworks/base/core/java/android/app/IActivityClientController.aidl

37. ActivityClientController#activityPaused

frameworks/base/services/core/java/com/android/server/wm/ActivityClientController.java
    @Override
    public void activityPaused(IBinder token) {
        final long origId = Binder.clearCallingIdentity();
        synchronized (mGlobalLock) {
            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "activityPaused");
            final ActivityRecord r = ActivityRecord.forTokenLocked(token);
            if (r != null) {
                r.activityPaused(false);
            }
            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
        }
        Binder.restoreCallingIdentity(origId);
    }

38. ActivityRecord#activityPaused

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

    void activityPaused(boolean timeout) {
        ProtoLog.v(WM_DEBUG_STATES, "Activity paused: token=%s, timeout=%b", appToken,  timeout);

        if (task != null) {

//移除超时,发送超时消息schedulePauseTimeout是在startPausingLocked中发送的,那时候是要去执行Client的pause操作
            removePauseTimeout();

            final ActivityRecord pausingActivity = task.getPausingActivity();
            if (pausingActivity == this) {
                ProtoLog.v(WM_DEBUG_STATES, "Moving to PAUSED: %s %s", this,
                        (timeout ? "(due to timeout)" : " (pause complete)"));

                //延迟layout window

                mAtmService.deferWindowLayout();
                try {
              task.completePauseLocked(true /* resumeNext */, null /* resumingActivity */);
                } finally {

                   //恢复ayout window
                    mAtmService.continueWindowLayout();
                }
                return;
            } else {
             ....
        }

        mDisplayContent.handleActivitySizeCompatModeIfNeeded(this);
        mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
    }
 

 39. Task#completePauseLocked

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

    @VisibleForTesting
    void completePauseLocked(boolean resumeNext, ActivityRecord resuming) {
        // Complete the pausing process of a pausing activity, so it doesn't make sense to operate on non-leaf tasks.完成暂停activity的暂停过程,因此对non-leaf tasks进行操作没有意义。
        warnForNonLeafTask("completePauseLocked");

//在startPausingLocked中赋值:mPausingActivity = prev;

        ActivityRecord prev = mPausingActivity;
        ProtoLog.v(WM_DEBUG_STATES, "Complete pause: %s", prev);

        if (prev != null) {
            prev.setWillCloseOrEnterPip(false);
            final boolean wasStopping = prev.isState(STOPPING);
            prev.setState(PAUSED, "completePausedLocked");
            if (prev.finishing) {如果prev在finishing
                // We will update the activity visibility later, no need to do in completeFinishing(). Updating visibility here might also making the next activities to be resumed, and could result in wrong app transition due to lack of previous activity information.

我们稍后会更新activity可见性,无需在 completeFinishing() 中执行。在此处更新可见性也可能使下一个activity resumed ,并且由于缺少以前的activity信息,可能会导致错误的应用转换。
                ProtoLog.v(WM_DEBUG_STATES, "Executing finish of activity: %s", prev);
                prev = prev.completeFinishing(false /* updateVisibility */,
                        "completePausedLocked");
            } else if (prev.hasProcess()) {
                ProtoLog.v(WM_DEBUG_STATES, "Enqueue pending stop if needed: %s "
                        + "wasStopping=%b visibleRequested=%b",  prev,  wasStopping,
                        prev.mVisibleRequested);
                if (prev.deferRelaunchUntilPaused) {
                    // Complete the deferred relaunch that was waiting for pause to complete.
                    ProtoLog.v(WM_DEBUG_STATES, "Re-launching after pause: %s", 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 {
                ProtoLog.v(WM_DEBUG_STATES, "App died during pause, not stopping: %s", 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.

activity可能在暂停之前冻结了屏幕。在这种情况下,请继续并删除此activity在屏幕上的冻结,因为它不再可见。
            if (prev != null) {
                prev.stopFreezingScreenLocked(true /*force*/);
            }

//如果不是以上情况,则说明prev已经pause完成,则mPausingActivity 置为空
            mPausingActivity = null;
        }

        if (resumeNext) {//传入的入参是true,会走入
            final Task topRootTask = mRootWindowContainer.getTopDisplayFocusedRootTask();
            if (topRootTask != null && !topRootTask.shouldSleepOrShutDownActivities()) {
                mRootWindowContainer.resumeFocusedTasksTopActivities(topRootTask, prev, null);
            } else {
                checkReadyForSleep();
                final ActivityRecord top =
                        topRootTask != null ? topRootTask.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 root task is not the just paused activity, we need to go ahead and resume it to ensure we complete an in-flight app switch.
                    mRootWindowContainer.resumeFocusedTasksTopActivities();
                }
            }
        }

        if (prev != null) {
            prev.resumeKeyDispatchingLocked();
        }

        mRootWindowContainer.ensureActivitiesVisible(resuming, 0, !PRESERVE_WINDOWS);

        // Notify when the task stack has changed, but only if visibilities changed (not just focus). Also if there is an active root pinned task - we always want to notify it about task stack changes, because its positioning may depend on it.
        if (mTaskSupervisor.mAppVisibilitiesChangedSinceLastPause
                || (getDisplayArea() != null && getDisplayArea().hasPinnedTask())) {
            mAtmService.getTaskChangeNotificationController().notifyTaskStackChanged();
            mTaskSupervisor.mAppVisibilitiesChangedSinceLastPause = false;
        }
    }

40. RootWindowContainer#resumeFocusedTasksTopActivities

frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
    boolean resumeFocusedTasksTopActivities( Task targetRootTask, ActivityRecord target, ActivityOptions targetOptions, boolean deferPause) {
        if (!mTaskSupervisor.readyToResume()) {
            return false;
        }

        boolean result = false;
//目标root task不是空并且targetRootTask.isTopRootTaskInDisplayArea或者焦点task等于targetRootTask
        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) {
                    // Simply update the result for targetRootTask because the targetRootTask had already resumed in above. We don't want to resume it again, especially in some cases, it would cause a second launch failure if app process was dead.只需更新 targetRootTask 的结果,因为 targetRootTask 已经在上面resumed了。我们不想再次resume它,特别是在某些情况下,如果应用程序进程已死,它会导致第二次启动失败。
                    resumedOnDisplay[0] |= curResult;
                    return;
                }
                if (rootTask.getDisplayArea().isTopRootTask(rootTask)
                        && topRunningActivity.isState(RESUMED)) {
                    // Kick off any lingering app transitions form the MoveTaskToFront operation, but only consider the top task and root-task on that display.从 MoveTaskToFront 操作开始任何延迟的应用程序转换,但只考虑该显示器上的顶级任务和根任务。
                    rootTask.executeAppTransition(targetOptions);
                } else {
                    resumedOnDisplay[0] |= topRunningActivity.makeActiveIfNeeded(target);
                }
            });
            result |= resumedOnDisplay[0];
            if (!resumedOnDisplay[0]) {
                // In cases when there are no valid activities (e.g. device just booted or launcher crashed) it's possible that nothing was resumed on a display. Requesting resume of top activity in focused root task explicitly will make sure that at least home activity is started and resumed, and no recursion occurs.
如果没有有效的activities(例如,设备刚刚启动或启动器崩溃),则显示器上可能没有可resume的activity。显式请求resume 焦点根任务中的顶级activity将确保至少启动和恢复home activity,并且不会发生递归。
                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;
    }
​

 37. RootWindowContainer#resumeFocusedTasksTopActivities

​

frameworks/base/services/core/java/com/android/server/wm/Task.java
    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);
                    // Doing so in order to prevent IndexOOB since hierarchy might changes while resuming activities, for example dismissing split-screen while starting non-resizeable activity.
这样做是为了防止 IndexOOB,因为在resume activities时层次结构可能会更改,例如在启动不可调整大小的activity时关闭分屏。
                    if (idx >= mChildren.size()) {
                        idx = mChildren.size() - 1;
                    }
                }
            }

            // 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 ActivityTaskSupervisor#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 ActivityTaskSupervisor#checkReadyForSleepLocked} is skipped.
当resume顶部activity时,可能需要暂停顶部activity(例如,返回到锁定屏幕)。我们在 {@link #resumeTopActivityUncheckedLocked} 中抑制正常的暂停逻辑,直到顶部activity resumed。我们在这里再次调用 {@link ActivityTaskSupervisor#checkReadyForSleepLocked},以确保发生任何必要的暂停逻辑。如果无论锁定屏幕如何都显示activity,则跳过对 {@link ActivityTaskSupervisor#checkReadyForSleepLocked} 的调用。
         final ActivityRecord next = topRunningActivity(true /* focusableOnly */);
            if (next == null || !next.canTurnScreenOn()) {
                checkReadyForSleep();
            }
        } finally {
            mInResumeTopActivity = false;
        }

        return someActivityResumed;
    }
​

41. 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()) {
            // Make sure we have executed any pending transitions, since there should be nothing left to do at this point.

确保我们已执行任何挂起的转换,因为此时应该没有什么可做的。
            executeAppTransition(options);
            // For devices that are not in fullscreen mode (e.g. freeform windows), it's possible we still want to check if the visibility of other windows have changed (e.g. bringing a fullscreen window forward to cover another freeform activity.)对于未处于全屏模式的设备(例如自由格式窗口),我们可能仍希望检查其他窗口的可见性是否已更改(例如,将全屏窗口向前移动以覆盖另一个自由格式活动)。
            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;
        }

        // If we are currently pausing an activity, then don't do anything until that is done.

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

            return false;
        }


        // If we are sleeping, and there is no resumed activity, and the top activity is paused, well that is the state we want.如果我们在sleeping,并且没有resumed的activity,并且顶级activity暂停,那么这就是我们想要的状态。
        if (mLastPausedActivity == next && shouldSleepOrShutDownActivities()) {
            // Make sure we have executed any pending transitions, since there should be nothing left to do at this point.

确保我们已执行任何挂起的转换,因为此时应该没有什么可做的。
            executeAppTransition(options);
            ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivityLocked: Going to sleep and"
                    + " all paused");
            return false;
        }

        // Make sure that the user who owns this activity is started.  If not, we will just leave it as is because someone should be bringing another user's activities to the top of the stack.

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

        // The activity may be waiting for stop, but that is no longer appropriate for it.

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

那么,我们为什么不在这里使用 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");
        }
        if (pausing) {
            ProtoLog.v(WM_DEBUG_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.

在这一点上,我们希望将即将到来的activity的过程放在 LRU 列表的顶部,因为我们知道我们很快就会需要它,如果它碰巧坐在最后,让它被杀死是一种浪费。
            if (next.attachedToProcess()) {
                next.app.updateProcessInfo(false /* updateServiceConnectionActivities */,
                        true /* activityChange */, false /* updateOomAdj */,
                        false /* addPendingTopUid */);
            } else if (!next.isProcessRunning()) {
                // Since the start-process is asynchronous, if we already know the process of next activity isn't running, we can start the process earlier to save the time to wait for the current activity to be paused.由于启动过程是异步的,如果我们已经知道下一个activity的进程没有运行,我们可以提前启动该过程,以节省等待当前activity暂停的时间。
                final boolean isTop = this == taskDisplayArea.getFocusedRootTask();
                mAtmService.startProcessAsync(next, false /* knownToBeDead */, isTop,
                        isTop ? "pre-top-activity" : "pre-activity");
            }
            if (lastResumed != null) {
                lastResumed.setWillCloseOrEnterPip(true);
            }
            return true;

        } else if (mResumedActivity == next && next.isState(RESUMED)
                && taskDisplayArea.allResumedActivitiesComplete()) {
            // It is possible for the activity to be resumed when we paused back stacks above if the next activity doesn't have to wait for pause to complete. So, nothing else to-do except: Make sure we have executed any pending transitions, since there should be nothing left to do at this point.如果下一个activity不必等待暂停完成,则当我们暂停上面的后退堆栈时,activity可能会resumed。因此,除了以下事项外,无需执行任何其他操作:确保我们已执行任何挂起的转换,因为此时应该没有什么可做的。
            executeAppTransition(options);
            ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivityLocked: Top activity resumed " + "(dontWaitForPause) %s", next);
            return true;
        }

        // If the most recent activity was noHistory but was only stopped rather than stopped+finished because the device went to sleep, we need to make sure to finish it as we're making a new activity topmost.

如果最近的 activity 是 noHistory,但由于设备进入睡眠状态而只是停止而不是停止 + 完成,我们需要确保在最顶层创建新 activity 时finish销毁它。
        if (shouldSleepActivities()) {
            mTaskSupervisor.finishNoHistoryActivitiesIfNeeded(next);
        }

        if (prev != null && prev != next && next.nowVisible) {

            // The next activity is already visible, so hide the previous activity's windows right now so we can show the new one ASAP. We only do this if the previous is finishing, which should mean it is on top of the one being resumed so hiding it quickly is good.  Otherwise, we want to do the normal route of allowing the resumed activity to be shown so we can decide if the previous should actually be hidden depending on whether the new one is found to be full-screen or not.

下一个activity 已经可见,因此现在隐藏上一个activity 的窗口,以便我们可以尽快显示新activity 。我们仅在前一个完成时才这样做,这应该意味着它位于正在恢复的顶部,因此快速隐藏它是好的。 否则,我们希望执行允许显示resumed activity 的正常路线,以便我们可以根据是否发现新activity 是全屏的来决定是否实际上应该隐藏以前的activity 。
            if (prev.finishing) {
                prev.setVisibility(false);
                if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
                        "Not waiting for visible to hide: " + prev   + ", nowVisible=" + next.nowVisible);
            } else {
                if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
                        "Previous already visible but still waiting to hide: " + prev
                                + ", nowVisible=" + next.nowVisible);
            }

        }

        // Launching this app's activity, make sure the app is no longer considered stopped.

        启动此应用的activity时,请确保不再将应用视为已停止。
        try {
            mTaskSupervisor.getActivityMetricsLogger()
                    .notifyBeforePackageUnstopped(next.packageName);
            mAtmService.getPackageManager().setPackageStoppedState(
                    next.packageName, false, next.mUserId); /* TODO: Verify if correct userid */
        } catch (RemoteException e1) {
        } catch (IllegalArgumentException e) {
            Slog.w(TAG, "Failed trying to unstop package "
                    + next.packageName + ": " + e);
        }

        // We are starting up the next activity, so tell the window manager that the previous one will be hidden soon.  This way it can know to ignore it when computing the desired screen orientation.

我们正在启动下一个activity,因此告诉窗口管理器上一个activity将很快被隐藏。 这样,它可以知道在计算所需的屏幕方向时忽略它。
        boolean anim = true;
        final DisplayContent dc = taskDisplayArea.mDisplayContent;
        if (prev != null) {
            if (prev.finishing) {
                if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
                        "Prepare close transition: prev=" + prev);
                if (mTaskSupervisor.mNoAnimActivities.contains(prev)) {
                    anim = false;
                    dc.prepareAppTransition(TRANSIT_NONE);
                } else {
                    dc.prepareAppTransition(TRANSIT_CLOSE);
                }
                prev.setVisibility(false);
            } else {

//第一次走此方法的时候会走入此处
                if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
                        "Prepare open transition: prev=" + prev);

10-08 23:28:37.913  1601  1817 V ActivityTaskManager: Prepare open transition: prev=ActivityRecord{38ca623 u0 com.android.launcher3/.uioverrides.QuickstepLauncher t6}
                if (mTaskSupervisor.mNoAnimActivities.contains(next)) {
                    anim = false;
                    dc.prepareAppTransition(TRANSIT_NONE);
                } else {
                    dc.prepareAppTransition(TRANSIT_OPEN,
                            next.mLaunchTaskBehind ? TRANSIT_FLAG_OPEN_BEHIND : 0);
                }
            }

        } else {
            if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare open transition: no previous");
            if (mTaskSupervisor.mNoAnimActivities.contains(next)) {
                anim = false;
                dc.prepareAppTransition(TRANSIT_NONE);
            } else {
                dc.prepareAppTransition(TRANSIT_OPEN);
            }
        }

        if (anim) {
            next.applyOptionsAnimation();
        } else {
            next.abortAndClearOptionsAnimation();
        }

        mTaskSupervisor.mNoAnimActivities.clear();

        if (next.attachedToProcess()) {
            if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resume running: " + next
                    + " stopped=" + next.stopped
                    + " visibleRequested=" + next.mVisibleRequested);

            // If the previous activity is translucent, force a visibility update of the next activity, so that it's added to WM's opening app list, and transition animation can be set up properly. For example, pressing Home button with a translucent activity in focus. Launcher is already visible in this case. If we don't add it to opening apps, maybeUpdateTransitToWallpaper() will fail to identify this as a TRANSIT_WALLPAPER_OPEN animation, and run some funny animation.

如果上一个activity是半透明的,会强制更新下一个activity的可见性,以便将其添加到 WM 的打开应用程序列表中,并且可以正确设置过渡动画。例如,按下主屏幕按钮时,半透明activity处于焦点。在这种情况下,启动器已经可见。如果我们不将其添加到打开的应用程序,也许UpdateTransitToWallpaper()将无法将其识别为TRANSIT_WALLPAPER_OPEN动画,并运行一些有趣的动画。
            final boolean lastActivityTranslucent = lastFocusedRootTask != null
                    && (lastFocusedRootTask.inMultiWindowMode()
                    || (lastFocusedRootTask.mLastPausedActivity != null
                    && !lastFocusedRootTask.mLastPausedActivity.occludesParent()));

            // This activity is now becoming visible.这activity现在变得可见。
            if (!next.mVisibleRequested || next.stopped || lastActivityTranslucent) {
                next.setVisibility(true);
            }

            // schedule launch ticks to collect information about slow apps.

            安排启动刻度以收集有关慢速应用的信息。
            next.startLaunchTickingLocked();

            ActivityRecord lastResumedActivity =
                    lastFocusedRootTask == null ? null : lastFocusedRootTask.getResumedActivity();
            final ActivityState lastState = next.getState();

            mAtmService.updateCpuStats();

            ProtoLog.v(WM_DEBUG_STATES, "Moving to RESUMED: %s (in existing)", next);

            next.setState(RESUMED, "resumeTopActivityInnerLocked");

            // Have the window manager re-evaluate the orientation of the screen based on the new activity order.让窗口管理器根据新的activity 顺序重新评估屏幕的方向。
            boolean notUpdated = true;

            // Activity should also be visible if set mLaunchTaskBehind to true (see ActivityRecord#shouldBeVisibleIgnoringKeyguard()).

如果将 mLaunchTaskBehind 设置为 true,则活动也应该可见(请参阅 ActivityRecord#shouldBeVisibleIgnoringKeyguard())。
            if (shouldBeVisible(next)) {
                // We have special rotation behavior when here is some active activity that requests specific orientation or Keyguard is locked. Make sure all activity visibilities are set correctly as well as the transition is updated if needed to get the correct rotation behavior. Otherwise the following call to update the orientation may cause incorrect configurations delivered to client as a result of invisible window resize.
                // TODO: Remove this once visibilities are set correctly immediately when starting an activity.

当这里有一些activity 请求特定方向或键盘锁被锁定时,我们有特殊的旋转行为。确保正确设置所有activity 可见性,并在需要时更新过渡以获得正确的旋转行为。否则,以下更新方向的调用可能会导致由于不可见的窗口大小调整而传递到客户端的错误配置。
 待办事项:在启动活动时,一旦正确设置了可见性,请立即删除此内容。
                notUpdated = !mRootWindowContainer.ensureVisibilityAndConfig(next, getDisplayId(),
                        true /* markFrozenIfConfigChanged */, false /* deferResume */);
            }

            if (notUpdated) {
                // The configuration update wasn't able to keep the existing instance of the activity, and instead started a new one. We should be all done, but let's just make sure our activity is still at the top and schedule another run if something weird happened.

配置更新无法保留activity的现有实例,而是启动了新实例。我们应该都完成了,但让我们确保我们的activity仍然处于顶部,如果发生奇怪的事情,请安排另一次运行。
                ActivityRecord nextNext = topRunningActivity();
                ProtoLog.i(WM_DEBUG_STATES, "Activity config changed during resume: "
                        + "%s, new next: %s", next, nextNext);
                if (nextNext != next) {
                    // Do over!
                    mTaskSupervisor.scheduleResumeTopActivities();
                }
                if (!next.mVisibleRequested || next.stopped) {
                    next.setVisibility(true);
                }
                next.completeResumeLocked();
                return true;
            }

            try {
                final ClientTransaction transaction =
                        ClientTransaction.obtain(next.app.getThread(), next.appToken);
                // Deliver all pending results.
                ArrayList<ResultInfo> a = next.results;
                if (a != null) {
                    final int N = a.size();
                    if (!next.finishing && N > 0) {
                        if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
                                "Delivering results to " + next + ": " + a);
                        transaction.addCallback(ActivityResultItem.obtain(a));
                    }
                }

                if (next.newIntents != null) {
                    transaction.addCallback(
                       NewIntentItem.obtain(next.newIntents, true /* resume */));
                }

                // Well the app will no longer be stopped. Clear app token stopped state in window manager if needed.该应用程序将不再停止。如果需要,在窗口管理器中清除应用程序令牌停止状态。
                next.notifyAppResumed(next.stopped);

                EventLogTags.writeWmResumeActivity(next.mUserId, System.identityHashCode(next),next.getTask().mTaskId, next.shortComponentName);

                mAtmService.getAppWarningsLocked().onResumeActivity(next);
                next.app.setPendingUiCleanAndForceProcessStateUpTo(mAtmService.mTopProcessState);
                next.abortAndClearOptionsAnimation();
                transaction.setLifecycleStateRequest(
                        ResumeActivityItem.obtain(next.app.getReportedProcState(),
                                dc.isNextTransitionForward()));
                mAtmService.getLifecycleManager().scheduleTransaction(transaction);

                ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivityLocked: Resumed %s", next);
            } catch (Exception e) {
                // Whoops, need to restart this activity!
                 //需要重新启动此activity!
                ProtoLog.v(WM_DEBUG_STATES, "Resume failed; resetting state to %s: " + "%s", lastState, next);
                next.setState(lastState, "resumeTopActivityInnerLocked");

                // lastResumedActivity being non-null implies there is a lastStack present.lastResumedActivity 为非空意味着存在 lastStack。
                if (lastResumedActivity != null) {
                    lastResumedActivity.setState(RESUMED, "resumeTopActivityInnerLocked");
                }

                Slog.i(TAG, "Restarting because process died: " + next);
                if (!next.hasBeenLaunched) {
                    next.hasBeenLaunched = true;
                } else if (SHOW_APP_STARTING_PREVIEW && lastFocusedRootTask != null && lastFocusedRootTask.isTopRootTaskInDisplayArea()) {
                    next.showStartingWindow(false /* taskSwitch */);
                }
                mTaskSupervisor.startSpecificActivity(next, true, false);
                return true;
            }

            // From this point on, if something goes wrong there is no way to recover the activity.从这一点开始,如果出现问题,则无法恢复activity。
            try {
                next.completeResumeLocked();
            } catch (Exception e) {
                // If any exception gets thrown, toss away this activity and try the next one.如果抛出任何异常,请放弃此activity并尝试下一个activity。
                Slog.w(TAG, "Exception thrown during resume of " + next, e);
                next.finishIfPossible("resume-exception", true /* oomAdj */);
                return true;
            }
        } else {
            // Whoops, need to restart this activity!
            //需要重新启动此activity!
            if (!next.hasBeenLaunched) {
                next.hasBeenLaunched = true;
            } else {
                if (SHOW_APP_STARTING_PREVIEW) {
                    next.showStartingWindow(false /* taskSwich */);
                }
                if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);
            }
            ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivityLocked: Restarting %s", next);
            mTaskSupervisor.startSpecificActivity(next, true, true);
        }

        return true;
    }

  • 9
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值