008.Android14 AMS 剖析—— Activity 启动分析之 pause 前台 Activity

9/3/2024

本文基于 android-14.0.0_r15 版本讲解

# 1.回顾

上一节,我们分析了,Activity 启动请求到达 SystemServer 端后,SystemServer 端主要要完成以下一些工作:

  1. 解析与处理请求参数,要启动那个 Activity,怎么启动(flags 等参数),是谁启动等等一些信息
  2. 修改窗口容器树,创建新的 ActivityRecord 与 Task 并挂载到窗口容器树中
  3. pause 源 Activity
  4. 启动新进程,触发 Application Activity 的初始化和启动生命周期回调

前面的章节已经分析了前两点,本节接着分析第三点。

# 2. 概述

如果你做过 App 的开发,应该非常熟悉 Acitivyt A 启动 Activty B 的生命周期调度情况:

Activity A          Activity B

onCreate
onStart
onResume
onPause                             -- 待分析的阶段             
                    onCreate
                    onStart
                    onResume
onStop       
1
2
3
4
5
6
7
8
9
10

接下来我们就来分析 Activity A onPause 的过程。

上一节说到 Activity 启动过程中,会调用到 resumeFocusedTasksTopActivities 方法,该方法会 pause 前一个 Activity,接下来我们就来分析一下这部分源码。

SystemServer 端的调用链如下:

RootWindowContainer::resumeFocusedTasksTopActivities
    Task::resumeTopActivityUncheckedLocked                      -- Task 就是新创建的目标 Task
        Task::resumeTopActivityInnerLocked
            TaskFragment::resumeTopActivity                     -- TaskFragmentTask 的父节点
                taskDisplayArea.pauseBackTasks                  -- DefaultTaskDisplayArea
                    Task::startPausing                          -- Launcher 所在的 Task
                        TaskFragment::schedulePauseActivity     -- 调用到父类 TaskFragment 中的方法
                            PauseActivityItem::obtain           -- 构建一个 PauseActivityItem 对象
                            ClientLifecycleManager::scheduleTransaction
                                transactionWithState            -- 构建一个 ClientTransaction 对象
                                scheduleTransaction
                                    ClientTransaction::schedule
                                        IApplicationThread::scheduleTransaction  -- 远程调用到 app 端

1
2
3
4
5
6
7
8
9
10
11
12
13
14

App 端的调用链如下:

sendMessage
    handleMessage
        mTransactionExecutor.execute(transaction)
            executeCallbacks(transaction)                               -- 执行回调
            executeLifecycleState                                       -- 执行生命周期
                lifecycleItem.execute
                    ClientTransactionHandler::handlePauseActivity
                        performPauseActivity
                            performPauseActivityIfNeeded
                                Instrumentation::callActivityOnPause
                                    Activity::performPause
                                        Activity::onPause
                lifecycleItem.postExecute
                    ActivityClient::activityPaused
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 2. 准备阶段

准备阶段主要是做一些特殊情况的判断,确定一些参数值。

resumeFocusedTasksTopActivities 方法的具体实现如下:

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

class RootWindowContainer extends WindowContainer<DisplayContent>
        implements DisplayManager.DisplayListener {

     //......
    boolean resumeFocusedTasksTopActivities(
            Task targetRootTask, ActivityRecord target, ActivityOptions targetOptions,
            boolean deferPause) {
       
        // ......

        boolean result = false;
        if (targetRootTask != null && (targetRootTask.isTopRootTaskInDisplayArea()
                || getTopDisplayFocusedRootTask() == targetRootTask)) { // 进入
            // 关注点
            // targetRootTask 就是刚创建的目标 Task
            result = targetRootTask.resumeTopActivityUncheckedLocked(target, targetOptions,
                    deferPause);
        }

        // ......

        return result;
    }
    //......        
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

从方法的名字 resumeFocusedTasksTopActivities 可以看出,这里是要 resume FocusedTasks 中的 TopActivities。

这里我们主要关注 resumeTopActivityUncheckedLocked 方法,名字可以看出是找到了 FocusedTasks,现在要 resume TopActivity:

    // 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()) { //叶子 Task 节点
                if (isFocusableAndVisible()) { // 有焦点且可见。  进入
                    someActivityResumed = resumeTopActivityInnerLocked(prev, options, deferPause);
                }
            } else {
                // ......
            }

            final ActivityRecord next = topRunningActivity(true /* focusableOnly */);
            if (next == null || !next.canTurnScreenOn()) {
                checkReadyForSleep();
            }
        } finally {
            mInResumeTopActivity = false;
        }

        return someActivityResumed;
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

判断当前 Task 是叶子 Task 节点,所谓叶子 Task 节点,就是该节点的子节点中没有 Task 类型的节点

接着判断当前节点是有焦点且可见。

当前节点满足这两个条件,接着调用 resumeTopActivityInnerLocked:

    // frameworks/base/services/core/java/com/android/server/wm/Task.java
    
    /*
        pre:名字有点迷惑性,实际是目标 ActivityRecord
    */
    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options,
            boolean deferPause) {
        if (!mAtmService.isBooting() && !mAtmService.isBooted()) { // 不进入
            // Not ready yet!
            return false;
        }

        //  topRunningActivity 返回的是目标 ActivityRecord,
        // 和 pre 是同一个对象
        final ActivityRecord topActivity = topRunningActivity(true /* focusableOnly */);
        if (topActivity == null) { // 不进入
            // There are no activities left in this task, let's look somewhere else.
            return resumeNextFocusableActivityWhenRootTaskIsEmpty(prev, options);
        }

        final boolean[] resumed = new boolean[1];
        final TaskFragment topFragment = topActivity.getTaskFragment(); //topFragment,目标 Task 的父节点 DefaultTaskFragment
        // 关注点
        resumed[0] = topFragment.resumeTopActivity(prev, options, deferPause);
        // 子节点处理,当前情景下应该是没有子节点的
        forAllLeafTaskFragments(f -> {
            if (topFragment == f) {
                return;
            }
            if (!f.canBeResumed(null /* starting */)) {
                return;
            }
            resumed[0] |= f.resumeTopActivity(prev, options, deferPause);
        }, true);
        return resumed[0];
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

这里的 pre topActivity 都是目标 ActivityRecord。

这里通过 topActivity.getTaskFragment 获取到目标 Task,接着调用目标 Task 对象的 resumeTopActivity 方法:

// frameworks/base/services/core/java/com/android/server/wm/TaskFragment.java
    final boolean resumeTopActivity(ActivityRecord prev, ActivityOptions options,
            boolean deferPause) {
        // 目标 Activity
        ActivityRecord next = topRunningActivity(true /* focusableOnly */);
        if (next == null || !next.canResumeByCompat()) {
            return false;
        }

        next.delayedResume = false;

        // If we are currently pausing an activity, then don't do anything until that is done.
        final boolean allPausedComplete = mRootWindowContainer.allPausedActivitiesComplete(); // true
        if (!allPausedComplete) { // 不进入
            ProtoLog.v(WM_DEBUG_STATES,
                    "resumeTopActivity: Skip resume: some activity pausing.");
            return false;
        }

        // DefaultTaskDisplayArea
        final TaskDisplayArea taskDisplayArea = getDisplayArea();

        // If the top activity is the resumed one, nothing to do.
        if (mResumedActivity == next && next.isState(RESUMED)
                && taskDisplayArea.allResumedActivitiesComplete()) { // 不进入
           // ......
        }

        // ......


        // The activity may be waiting for stop, but that is no longer
        // appropriate for it.
        mTaskSupervisor.mStoppingActivities.remove(next);

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

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

        ActivityRecord lastResumed = null;
        // 目标 task
        final Task lastFocusedRootTask = taskDisplayArea.getLastFocusedRootTask();
        if (lastFocusedRootTask != null && lastFocusedRootTask != getRootTaskFragment().asTask()) { // 进入
            // 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.

            lastResumed = lastFocusedRootTask.getTopResumedActivity(); // QuickstepLauncher
        }

        // 重点关注
        boolean pausing = !deferPause && taskDisplayArea.pauseBackTasks(next);

        // ......
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

调用 Task 的 getDisplayArea 方法获取到 Task 的 TaskDisplayArea 类型父节点。也就是 DefualtTaskDisplayArea

接着调用 taskDisplayArea.pauseBackTasks 方法:

# 3. 发起 Pause 远程调用

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

    // resuming 就是目标 ActivityRecord
    boolean pauseBackTasks(ActivityRecord resuming) {
        final int[] someActivityPaused = {0};
        forAllLeafTasks(leafTask -> { // 遍历
            // Check if the direct child resumed activity in the leaf task needed to be paused if
            // the leaf task is not a leaf task fragment.
            if (!leafTask.isLeafTaskFragment()) {
                final ActivityRecord top = topRunningActivity();
                final ActivityRecord resumedActivity = leafTask.getResumedActivity();
                if (resumedActivity != null && top.getTaskFragment() != leafTask) {
                    // Pausing the resumed activity because it is occluded by other task fragment.
                    if (leafTask.startPausing(false /* uiSleeping*/, resuming, "pauseBackTasks")) {
                        someActivityPaused[0]++;
                    }
                }
            }

            leafTask.forAllLeafTaskFragments((taskFrag) -> {
                final ActivityRecord resumedActivity = taskFrag.getResumedActivity();
                if (resumedActivity != null && !taskFrag.canBeResumed(resuming)) {
                    // taskFrag 就是 QuickstepLauncher
                    if (taskFrag.startPausing(false /* uiSleeping*/, resuming, "pauseBackTasks")) { //会走到这
                        someActivityPaused[0]++;
                    }
                }
            }, true /* traverseTopToBottom */);
        }, true /* traverseTopToBottom */);
        return someActivityPaused[0] > 0;
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

这里会对窗口树结构进行局部条件遍历,找到符合要求的 Task 节点后,这里要求主要是指栈顶的 ActivityRecord 是 resumed 状态的,当前场景就是 launcher 。接着调用 Task startPausing 方法,向 App 发起 Binder RPC 调用,pause Activity。

# 3.1 窗口树的局部条件遍历

所谓树的局部条件遍历,就是遍历每一个节点,取出符合条件的节点,传入回调方法。

具体我们看代码:

TaskDisplayArea 对象的 forAllLeafTasks 方法定义在父类 WindowContainer 中:

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

    void forAllLeafTasks(Consumer<Task> callback, boolean traverseTopToBottom) {
        final int count = mChildren.size();
        if (traverseTopToBottom) { // traverseTopToBottom 值为 true,走这个分支
            for (int i = count - 1; i >= 0; --i) {
                mChildren.get(i).forAllLeafTasks(callback, traverseTopToBottom);
            }
        } else {
            for (int i = 0; i < count; i++) {
                mChildren.get(i).forAllLeafTasks(callback, traverseTopToBottom);
            }
        }
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14

遍历 TaskDisplayArea 的所有子节点,然后调用子节点的 forAllLeafTasks 方法。

当前情景下 TaskDisplayArea 的子节点情况如下:

20240311215246

三个子节点的类型均为 Task,接着就会调用到 Task 的 forAllLeafTasks 方法:

// frameworks/base/services/core/java/com/android/server/wm/Task.java
    void forAllLeafTasks(Consumer<Task> callback, boolean traverseTopToBottom) {
        final int count = mChildren.size();
        boolean isLeafTask = true;
        if (traverseTopToBottom) {
            for (int i = count - 1; i >= 0; --i) {
                final Task child = mChildren.get(i).asTask();
                if (child != null) {
                    isLeafTask = false;
                    child.forAllLeafTasks(callback, traverseTopToBottom);
                }
            }
        } else {
            for (int i = 0; i < count; i++) {
                final Task child = mChildren.get(i).asTask();
                if (child != null) {
                    isLeafTask = false;
                    child.forAllLeafTasks(callback, traverseTopToBottom);
                }
            }
        }
        if (isLeafTask) callback.accept(this);
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

Task 的字节点可以是 Task,也可以是 ActivityRecord。

Task 中定义有 asTask() 方法:

    // frameworks/base/services/core/java/com/android/server/wm/Task.java
    @Override
    Task asTask() {
        // I'm a task!
        return this;
    }
1
2
3
4
5
6

ActivityRecord 中 asTask() 方法实现在其父类 WindowContainor 中:

    // frameworks/base/services/core/java/com/android/server/wm/WindowContainer.java
    Task asTask() {
        return null;
    }
1
2
3
4

回到 Task 的 forAllLeafTasks 方法中,这里会对 Task 的子节点进行遍历:

  • 如果子节点是 Task 类型,asTask 方法返回的不是空,继续调用子节点的 forAllLeafTasks 方法
  • 如果子节点是 ActivityRcord 类型,asTask 方法返回空,isLeafTask 的值会是 true,就会调用传入的回调方法 callback.accept(this),并将当前 Task 作为参数传入

对于 forAllLeafTasks 方法,我们简单总结一下:

  • 找到 Task 类型的子节点
  • 如果该节点的子节点中有 ActivityRecord,调用传入的回调方法 callback.accept,并传入 Task 对象

接下来我们来看看回调方法的实现,回调方法是一个拉姆达表达式:

        // 主要关注回调
        forAllLeafTasks(leafTask -> {
            // Check if the direct child resumed activity in the leaf task needed to be paused if
            // the leaf task is not a leaf task fragment.
            if (!leafTask.isLeafTaskFragment()) {
                final ActivityRecord top = topRunningActivity();
                final ActivityRecord resumedActivity = leafTask.getResumedActivity();
                if (resumedActivity != null && top.getTaskFragment() != leafTask) {
                    // Pausing the resumed activity because it is occluded by other task fragment.
                    if (leafTask.startPausing(false /* uiSleeping*/, resuming, "pauseBackTasks")) {
                        someActivityPaused[0]++;
                    }
                }
            }

            leafTask.forAllLeafTaskFragments((taskFrag) -> {
                final ActivityRecord resumedActivity = taskFrag.getResumedActivity();
                if (resumedActivity != null && !taskFrag.canBeResumed(resuming)) {
                    // taskFrag 就是 QuickstepLauncher
                    if (taskFrag.startPausing(false /* uiSleeping*/, resuming, "pauseBackTasks")) { //会走到这
                        someActivityPaused[0]++;
                    }
                }
            }, true /* traverseTopToBottom */);
        }, true /* traverseTopToBottom */);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

前面分析出 leafTask 的类型是 Task,回调方法中先调用 Task 的 isLeafTaskFragment 方法做一个判断:

isLeafTaskFragment 方法定义在 Task 的父类 TaskFragment 中:

    // frameworks/base/services/core/java/com/android/server/wm/TaskFragment.java
    boolean isLeafTaskFragment() {
        for (int i = mChildren.size() - 1; i >= 0; --i) {
            if (mChildren.get(i).asTaskFragment() != null) {
                return false;
            }
        }
        return true;
    }
1
2
3
4
5
6
7
8
9

这里遍历 Task 的子节点,并调用子节点对象的 asTaskFragment 方法,Task 的子节点类型可以是 Task 和 ActivityRecord,他们的 asTaskFragment 方法均实现在父类 WindowContainer 中:

    TaskFragment asTaskFragment() {
        return null;
    }
1
2
3

这里返回 null,也就是意味着 isLeafTaskFragment 永远返回 true。

也就是说回调方法中的第一个 if 是不会执行到的。

接着会调用到 Task 的 forAllLeafTaskFragments 方法:

    @Override
    void forAllLeafTaskFragments(Consumer<TaskFragment> callback, boolean traverseTopToBottom) {
        final int count = mChildren.size();
        boolean isLeafTaskFrag = true;
        if (traverseTopToBottom) {
            for (int i = count - 1; i >= 0; --i) {
                final TaskFragment child = mChildren.get(i).asTaskFragment();
                if (child != null) {
                    isLeafTaskFrag = false;
                    child.forAllLeafTaskFragments(callback, traverseTopToBottom);
                }
            }
        } else {
            for (int i = 0; i < count; i++) {
                final TaskFragment child = mChildren.get(i).asTaskFragment();
                if (child != null) {
                    isLeafTaskFrag = false;
                    child.forAllLeafTaskFragments(callback, traverseTopToBottom);
                }
            }
        }
        if (isLeafTaskFrag) callback.accept(this);
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

执行逻辑和前面的 forAllLeafTasks 类似。

最终会执行到回调方法 callback.accept,传入的参数是当前 Task。

最终,对于每一个叶子 Task 节点会执行下面的回调:

            leafTask.forAllLeafTaskFragments((taskFrag) -> {
                final ActivityRecord resumedActivity = taskFrag.getResumedActivity(); // 获取到 Task 中的 resumed 状态的 ActivityRecord
                if (resumedActivity != null && !taskFrag.canBeResumed(resuming)) 
                    if (taskFrag.startPausing(false /* uiSleeping*/, resuming, "pauseBackTasks")) { //会走到这
                        someActivityPaused[0]++;
                    }
                }
            }, true /* traverseTopToBottom */);
1
2
3
4
5
6
7
8

# 3.2 发起远程调用,pause 前一个 Activity

接着会执行到源 Task 的 startPausing 方法.

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

    final boolean startPausing(boolean uiSleeping, ActivityRecord resuming, String reason) {
        return startPausing(mTaskSupervisor.mUserLeaving, uiSleeping, resuming, reason);
    }

    boolean startPausing(boolean userLeaving, boolean uiSleeping, ActivityRecord resuming,
            String reason) {
        if (!hasDirectChildActivities()) { // 不进入
            return false;
        }

        ProtoLog.d(WM_DEBUG_STATES, "startPausing: taskFrag =%s " + "mResumedActivity=%s", this,
                mResumedActivity);

        if (mPausingActivity != null) { // 不进入
            Slog.wtf(TAG, "Going to pause when pause is already pending for " + mPausingActivity
                    + " state=" + mPausingActivity.getState());
            if (!shouldSleepActivities()) {
                // Avoid recursion among check for sleep and complete pause during sleeping.
                // Because activity will be paused immediately after resume, just let pause
                // be completed by the order of activity paused from clients.
                completePause(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);
        // Launcher 中的 Activity
        mPausingActivity = prev;
        mLastPausedActivity = prev;
        if (!prev.finishing && prev.isNoHistory()
                && !mTaskSupervisor.mNoHistoryActivities.contains(prev)) {
            mTaskSupervisor.mNoHistoryActivities.add(prev);
        }
        // 设置状态,实际会通过 binder 通知到 App,不是重点
        prev.setState(PAUSING, "startPausingLocked");
        prev.getTask().touchActiveTime();

        mAtmService.updateCpuStats();

        boolean pauseImmediately = false;
        boolean shouldAutoPip = false;
        if (resuming != null) { // 进入
            // We do not want to trigger auto-PiP upon launch of a translucent activity.
            final boolean resumingOccludesParent = resuming.occludesParent();
            // Resuming the new resume activity only if the previous activity can't go into Pip
            // since we want to give Pip activities a chance to enter Pip before resuming the
            // next activity.
            final boolean lastResumedCanPip = prev.checkEnterPictureInPictureState(
                    "shouldAutoPipWhilePausing", userLeaving);
            if (userLeaving && resumingOccludesParent && lastResumedCanPip
                    && prev.pictureInPictureArgs.isAutoEnterEnabled()) {
                shouldAutoPip = true;
            } else if (!lastResumedCanPip) {
                // If the flag RESUME_WHILE_PAUSING is set, then continue to schedule the previous
                // activity to be paused.
                pauseImmediately = (resuming.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0;
            } else {
                // The previous activity may still enter PIP even though it did not allow auto-PIP.
            }
        }

        if (prev.attachedToProcess()) {
            if (shouldAutoPip) {
                prev.mPauseSchedulePendingForPip = true;
                boolean didAutoPip = mAtmService.enterPictureInPictureMode(
                        prev, prev.pictureInPictureArgs, false /* fromClient */);
                ProtoLog.d(WM_DEBUG_STATES, "Auto-PIP allowed, entering PIP mode "
                        + "directly: %s, didAutoPip: %b", prev, didAutoPip);
            } else { // 走这里
                schedulePauseActivity(prev, userLeaving, pauseImmediately,
                        false /* autoEnteringPip */, reason);
            }
        } else {
            mPausingActivity = null;
            mLastPausedActivity = null;
            mTaskSupervisor.mNoHistoryActivities.remove(prev);
        }

        // ......
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95

接着会调用到 schedulePauseActivity,在这个方法中会向源 App 发起远程调用:

// frameworks/base/services/core/java/com/android/server/wm/TaskFragment.java
    void schedulePauseActivity(ActivityRecord prev, boolean userLeaving,
            boolean pauseImmediately, boolean autoEnteringPip, String reason) {
        ProtoLog.v(WM_DEBUG_STATES, "Enqueueing pending pause: %s", prev);
        try {
            prev.mPauseSchedulePendingForPip = false;
            EventLogTags.writeWmPauseActivity(prev.mUserId, System.identityHashCode(prev),
                    prev.shortComponentName, "userLeaving=" + userLeaving, reason);

            mAtmService.getLifecycleManager().scheduleTransaction(prev.app.getThread(),
                    prev.token, PauseActivityItem.obtain(prev.finishing, userLeaving,
                            prev.configChangeFlags, pauseImmediately, autoEnteringPip));
        } catch (Exception e) {
            // Ignore exception, if process died other code will cleanup.
            Slog.w(TAG, "Exception thrown during pause", e);
            mPausingActivity = null;
            mLastPausedActivity = null;
            mTaskSupervisor.mNoHistoryActivities.remove(prev);
        }
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

关键步骤:

  • getLifecycleManager
  • PauseActivityItem.obtain:构造一个 PauseActivityItem 对象
  • scheduleTransaction

接着调用 mService.getLifecycleManager().scheduleTransaction 向 App 端发起 Binder RPC 调用:

    // frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
    private final ClientLifecycleManager mLifecycleManager;

    ClientLifecycleManager getLifecycleManager() {
        return mLifecycleManager;
    }

    // /frameworks/base/core/java/android/app/servertransaction/ClientTransaction.java
    /**
     * Schedule a single lifecycle request or callback to client activity.
     * @param client Target client.
     * @param activityToken Target activity token.
     * @param stateRequest A request to move target activity to a desired lifecycle state.
     * @throws RemoteException
     *
     * @see ClientTransactionItem
     */
    void scheduleTransaction(@NonNull IApplicationThread client, @NonNull IBinder activityToken,
            @NonNull ActivityLifecycleItem stateRequest) throws RemoteException {
        final ClientTransaction clientTransaction = transactionWithState(client, activityToken,
                stateRequest);
        scheduleTransaction(clientTransaction);
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

接着调用重载 scheduleTransaction:

    // frameworks/base/services/core/java/com/android/server/wm/ClientLifecycleManager.java
    void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
        final IApplicationThread client = transaction.getClient();
        // 关注点
        transaction.schedule();
        if (!(client instanceof Binder)) {
            // If client is not an instance of Binder - it's a remote call and at this point it is
            // safe to recycle the object. All objects used for local calls will be recycled after
            // the transaction is executed on client in ActivityThread.
            transaction.recycle();
        }
    }    

1
2
3
4
5
6
7
8
9
10
11
12
13

接着调用 schedule:


 // /frameworks/base/core/java/android/app/servertransaction/ClientTransaction.java
    /** Target client. */
    private IApplicationThread mClient;

    /**
     * Schedule the transaction after it was initialized. It will be send to client and all its
     * individual parts will be applied in the following sequence:
     * 1. The client calls {@link #preExecute(ClientTransactionHandler)}, which triggers all work
     *    that needs to be done before actually scheduling the transaction for callbacks and
     *    lifecycle state request.
     * 2. The transaction message is scheduled.
     * 3. The client calls {@link TransactionExecutor#execute(ClientTransaction)}, which executes
     *    all callbacks and necessary lifecycle transitions.
     */
    public void schedule() throws RemoteException {
        mClient.scheduleTransaction(this);
    }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

层层调用到 IApplicationThread 的 scheduleTransaction 方法,这是一个 Binder RPC 调用:

远程调用 App 端的 scheduleTransaction 方法,调用该方法后,App 端会 pause 前一个 Activity。

ATMS 远程调用到 App 端的 scheduleTransaction 方法:

// /frameworks/base/core/java/android/app/ActivityThread.java

private class ApplicationThread extends IApplicationThread.Stub {
        // ......
        @Override
        public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
            ActivityThread.this.scheduleTransaction(transaction);
        }
        // ......
}
1
2
3
4
5
6
7
8
9
10

接着调用到 App 端中 ActivityThread 的 scheduleTransaction 方法:

/** Prepare and schedule transaction for execution. */
void scheduleTransaction(ClientTransaction transaction) {
    transaction.preExecute(this);
    sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
}
1
2
3
4
5

这里会发送一个 Message,ActivityThread 中的 Handler 中会处理到这个 Message:

// /frameworks/base/core/java/android/app/ActivityThread.java
        public void handleMessage(Message msg) {
                case EXECUTE_TRANSACTION:
                    // 从 Message 中取出消息
                    final ClientTransaction transaction = (ClientTransaction) msg.obj;
                    // 执行消息
                    mTransactionExecutor.execute(transaction);
                    if (isSystem()) {
                        // Client transactions inside system process are recycled on the client side
                        // instead of ClientLifecycleManager to avoid being cleared before this
                        // message is handled.
                        transaction.recycle();
                    }
                    // TODO(lifecycler): Recycle locally scheduled transactions.
                    break;            
        }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  • 从 Message 中取出消息
  • 执行消息

接着我们来看执行消息的过程:


    // /frameworks/base/core/java/android/app/servertransaction/TransactionExecutor.java
    public void execute(ClientTransaction transaction) {
        if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "Start resolving transaction");

        // ......

        // 执行回调
        executeCallbacks(transaction);

        // 执行生命周期
        executeLifecycleState(transaction);
        mPendingActions.clear();
        if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "End resolving transaction");
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

接着调用 executeLifecycleState 来执行生命周期:

    // /frameworks/base/core/java/android/app/servertransaction/TransactionExecutor.java
        /** Transition to the final state if requested by the transaction. */
    private void executeLifecycleState(ClientTransaction transaction) {

        // 从 ClientTransaction 中拿到 ActivityLifecycleItem,这里是子类 PauseActivityItem
        final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();
        
        // ......

        // token 是一个索引值
        // 通过 token 可以拿到 ActivityClientRecord,ActivityClientRecord 对象存在于 App 端的,用于描述描述一个 Activity
        final IBinder token = transaction.getActivityToken();
        final ActivityClientRecord r = mTransactionHandler.getActivityClient(token);
        if (DEBUG_RESOLVER) {
            Slog.d(TAG, tId(transaction) + "Resolving lifecycle state: "
                    + lifecycleItem + " for activity: "
                    + getShortActivityName(token, mTransactionHandler));
        }

        if (r == null) {
            // Ignore requests for non-existent client records for now.
            return;
        }

        // Cycle to the state right before the final requested state.
        cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */, transaction);

        // Execute the final transition with proper parameters.
        // 执行生命周期
        lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
        // 执行生命周期后的操作也要关心
        lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

接着执行 PauseActivityItem 的 execute:

    // /frameworks/base/core/java/android/app/servertransaction/PauseActivityItem.java
    @Override
    public void execute(ClientTransactionHandler client, IBinder token,
            PendingTransactionActions pendingActions) {
        Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
        // 执行回调
        client.handlePauseActivity(token, mFinished, mUserLeaving, mConfigChanges, pendingActions,
                "PAUSE_ACTIVITY_ITEM");
        Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
    }
1
2
3
4
5
6
7
8
9
10

client 的具体类型是 ActivityThread 接着执行到 ActivityThread 的 handlePauseActivity 方法:

// /frameworks/base/core/java/android/app/ActivityThread.java

    @Override
    public void handlePauseActivity(IBinder token, boolean finished, boolean userLeaving,
            int configChanges, PendingTransactionActions pendingActions, String reason) {
        ActivityClientRecord r = mActivities.get(token);
        if (r != null) {
            if (userLeaving) { // userLeaving 相关的回调
                performUserLeavingActivity(r);
            }

            r.activity.mConfigChangeFlags |= configChanges;
            // 关注点
            performPauseActivity(r, finished, reason, pendingActions);

            // Make sure any pending writes are now committed.
            if (r.isPreHoneycomb()) {
                QueuedWork.waitToFinish();
            }
            mSomeActivitiesChanged = true;
        }
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

接着调用 performPauseActivity:

    // /frameworks/base/core/java/android/app/ActivityThread.java

    /**
     * Pause the activity.
     * @return Saved instance state for pre-Honeycomb apps if it was saved, {@code null} otherwise.
     */
    private Bundle performPauseActivity(ActivityClientRecord r, boolean finished, String reason,
            PendingTransactionActions pendingActions) {
        
        //......

        // 关注点
        performPauseActivityIfNeeded(r, reason);

        //......
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

接着调用 performPauseActivityIfNeeded

    // /frameworks/base/core/java/android/app/ActivityThread.java
    private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) {
        
        // ......

        try {
            r.activity.mCalled = false;
            // 关注点
            mInstrumentation.callActivityOnPause(r.activity);
            if (!r.activity.mCalled) {
                throw new SuperNotCalledException("Activity " + safeToComponentShortString(r.intent)
                        + " did not call through to super.onPause()");
            }
        } catch (SuperNotCalledException e) {
            throw e;
        } catch (Exception e) {
            if (!mInstrumentation.onException(r.activity, e)) {
                throw new RuntimeException("Unable to pause activity "
                        + safeToComponentShortString(r.intent) + ": " + e.toString(), e);
            }
        }
        r.setState(ON_PAUSE);
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

接着会调用 Activity 的 callActivityOnPause:

    // /frameworks/base/core/java/android/app/Instrumentation.java
    /**
     * Perform calling of an activity's {@link Activity#onPause} method.  The
     * default implementation simply calls through to that method.
     * 
     * @param activity The activity being paused.
     */
    public void callActivityOnPause(Activity activity) {
        activity.performPause();
    }
1
2
3
4
5
6
7
8
9
10

接着执行 Activity 的 performPause 方法:

// /frameworks/base/core/java/android/app/Activity.java
    final void performPause() {
        dispatchActivityPrePaused();
        mDoReportFullyDrawn = false;
        mFragments.dispatchPause();
        mCalled = false;
        onPause();
        writeEventLog(LOG_AM_ON_PAUSE_CALLED, "performPause");
        mResumed = false;
        if (!mCalled && getApplicationInfo().targetSdkVersion
                >= android.os.Build.VERSION_CODES.GINGERBREAD) {
            throw new SuperNotCalledException(
                    "Activity " + mComponent.toShortString() +
                    " did not call through to super.onPause()");
        }
        dispatchActivityPostPaused();
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

在这里就会执行到 Activity 的 onPause 生命周期方法。

生命周期执行完后,接下来回到之前的 executeLifecycleState 方法中:

        /** Transition to the final state if requested by the transaction. */
    private void executeLifecycleState(ClientTransaction transaction) {
        // 拿到 ActivityLifecycleItem,这里是子类 PauseActivityItem
        final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();
        
        // ......

        // 执行生命周期
        lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
        lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
    }
1
2
3
4
5
6
7
8
9
10
11

在调用 execute 方法,执行完 onPause 生命周期方法后,接着会调用到 lifecycleItem.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.
        ActivityClient.getInstance().activityPaused(token);
    }
1
2
3
4
5
6
7
8
9
10

在这里,会调用到 ActivityClient 的 activityPaused 方法。这部分内容我们就留在下一节在分析了。

# 参考资料