Android14 AMS 剖析—— Activity 启动分析之 Task 的构建

9/2/2024

程序员这一行,想做好,一定要定好目标,脚踏实地,持之以恒,日积月累,定能拨开云雾见天日,守得云开见月明!

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

# 1.回顾

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

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

上一节主要分析第一点和第二点部分内容。本节我们接着分析第二点中 Task 的构建过程。

# 2. startActivityUnchecked 方法整体流程

接上一节,我们接下来分析 startActivityUnchecked 方法的实现。

整体的调用链如下:

ActivityStarter::startActivityUnchecked
    ActivityStarter::startActivityInner        
    ActivityStarter::getOrCreateRootTask                
        ActivityStarter::setNewTask            
        Task::moveToFront                       
        RootWindowContainer::resumeFocusedTasksTopActivities   
            Task::resumeTopActivityUncheckedLocked
                Task::resumeTopActivityInnerLocked
                    TaskFragment::resumeTopActivity      
                        TaskDisplayArea::pauseBackTasks                   
                        ActivityTaskManagerService::startProcessAsync     
1
2
3
4
5
6
7
8
9
10
11

时序图如下:

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

    private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, ActivityOptions options, Task inTask,
            TaskFragment inTaskFragment, @BalCode int balCode,
            NeededUriGrants intentGrants, int realCallingUid) {
      
        // ......
      
        try {
            mService.deferWindowLayout(); // 暂停 window 布局
            transitionController.collect(r);
            try {
                Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner");

                // 关注点
                result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,
                        startFlags, options, inTask, inTaskFragment, balCode,
                        intentGrants, realCallingUid);
            } finally {
                Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
                startedActivityRootTask = handleStartResult(r, options, result, newTransition,
                        remoteTransition);
            }
        } finally {
            mService.continueWindowLayout(); // 继续 window 布局
        }
      
        postStartActivityProcessing(r, result, startedActivityRootTask);

        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
28
29
30
31
32
33

接着会调用 startActivityInner 方法。

调用 startActivityInner 方法之前会调用 deferWindowLayout 方法暂停布局操作,之后会调用 continueWindowLayout 方法继续布局操作,这个会在 wms 的部分来讲解,这里先知道有这个流程。

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

   /**
     * Start an activity and determine if the activity should be adding to the top of an existing
     * task or delivered new intent to an existing activity. Also manipulating the activity task
     * onto requested or valid root-task/display.
     *
     * Note: This method should only be called from {@link #startActivityUnchecked}.
     */
    // TODO(b/152429287): Make it easier to exercise code paths through startActivityInner
    @VisibleForTesting
    int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, ActivityOptions options, Task inTask,
            TaskFragment inTaskFragment, @BalCode int balCode,
            NeededUriGrants intentGrants, int realCallingUid) {
      
        // 初始化各类参数
        setInitialState(r, options, inTask, inTaskFragment, startFlags, sourceRecord,
                voiceSession, voiceInteractor, balCode, realCallingUid);

        // 根据 launchMode 和 Intent 中的 FLAG_ACTIVITY_NEW_TASK 等 flag 综合计算 activity 的启动模式,
	    // 结果保存在 mLaunchFlags 中。计算的过程不仅要考虑目标 activity 的 launchMode,
	    // 也要考虑原来 activity 的 launchMode 和 Intent 中所带着的 flag
        computeLaunchingTaskFlags();
      
        mIntent.setFlags(mLaunchFlags); //270532608

        boolean dreamStopping = false;

        // ......

  
        // launcher 中有两个 Task
        // launcher 中的根 Task
        final Task prevTopRootTask = mPreferredTaskDisplayArea.getFocusedRootTask();
        // launcher 中的叶子 Task
        final Task prevTopTask = prevTopRootTask != null ? prevTopRootTask.getTopLeafTask() : null;
        // null,没有可以复用的 Task
        final Task reusedTask = getReusableTask();

        // ......

        // null,computeTargetTask 查找是否已经存在目标 Task,当前场景下没有,返回 null
        final Task targetTask = reusedTask != null ? reusedTask : computeTargetTask();
        // true
        final boolean newTask = targetTask == null;
        mTargetTask = targetTask; // null

        // 关注点 1
        // 计算启动参数,结果保存在 mLaunchParams 中 
        computeLaunchParams(r, sourceRecord, targetTask);

        // Check if starting activity on given task or on a new task is allowed.
        int startResult = isAllowedToStart(r, newTask, targetTask); // 0
      
        // ......

        final ActivityRecord targetTaskTop = newTask
                ? null : targetTask.getTopNonFinishingActivity(); // null
        if (targetTaskTop != null) { // 不进入
            // ......
        } else { //进入
            mAddingToTask = true;
        }
        
        // 待启动的 Activity 已经在栈顶情况的处理,当前场景不涉及
        // 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); // 0
            if (startResult != START_SUCCESS) { //不进入 
                return startResult;
            }
        }

        if (mTargetRootTask == null) { // 进入
            // 关注点 2
            // 创建一个 Task 对象,也就是目标 Task
            mTargetRootTask = getOrCreateRootTask(mStartActivity, mLaunchFlags, targetTask,
                    mOptions);
        }
        if (newTask) { // 进入
            final Task taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
                    ? mSourceRecord.getTask() : null; // null
            // 关注点 3
            setNewTask(taskToAffiliate); // 把目标 ActivityRecord 插入新创建的 Task
        } else if (mAddingToTask) {
            addOrReparentStartingActivity(targetTask, "adding to task");
        }

        if (!mAvoidMoveToFront && mDoResume) { // 进入

            // 关注点 4
            // Task 在窗口容器树中是 TaskDisplayArea 的子节点
            // 移动新创建的 Task 到 TaskDisplayArea 的子节点中的栈顶位置
            mTargetRootTask.getRootTask().moveToFront("reuseOrNewTask", targetTask);
            if (!mTargetRootTask.isTopRootTaskInDisplayArea() && mService.isDreaming()
                    && !dreamStopping) { // 不进入
                // 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;
            }
        }

        // 给目标 Activity 添加 Uri 权限,了解
        mService.mUgmInternal.grantUriPermissionUncheckedFromIntent(intentGrants,
                mStartActivity.getUriPermissionsLocked());
        
        // ......
        final Task startedTask = mStartActivity.getTask();
        if (newTask) {
            EventLogTags.writeWmCreateTask(mStartActivity.mUserId, startedTask.mTaskId,
                    startedTask.getRootTaskId(), startedTask.getDisplayId());
        }
        mStartActivity.logStartActivity(EventLogTags.WM_CREATE_ACTIVITY, startedTask);

        mStartActivity.getTaskFragment().clearLastPausedActivity();


        // 电源管理,了解 
        mRootWindowContainer.startPowerModeLaunchIfNeeded(
                false /* forceSend */, mStartActivity);

        final boolean isTaskSwitch = startedTask != prevTopTask;
        // 关注点 5
        // 调整目标 Task 内部参数,开启转场动画(启动白屏),为启动 Activity 做好准备
        mTargetRootTask.startActivityLocked(mStartActivity, topRootTask, newTask, isTaskSwitch,
                mOptions, sourceRecord);
        if (mDoResume) { // 进入
            final ActivityRecord topTaskActivity = startedTask.topRunningActivityLocked();
            if (!mTargetRootTask.isTopActivityFocusable()
                    || (topTaskActivity != null && topTaskActivity.isTaskOverlay()
                    && mStartActivity != topTaskActivity)) { // 不进入
                // ......
            } else {
              
                // ......

                // 关注点 6
                // 生命周期处理
                mRootWindowContainer.resumeFocusedTasksTopActivities(
                        mTargetRootTask, mStartActivity, mOptions, mTransientLaunch);
            }
        }
        mRootWindowContainer.updateUserRootTask(mStartActivity.mUserId, mTargetRootTask);

        // Update the recent tasks list immediately when the activity starts
        mSupervisor.mRecentTasks.add(startedTask);
        mSupervisor.handleNonResizableTaskIfNeeded(startedTask,
                mPreferredWindowingMode, mPreferredTaskDisplayArea, mTargetRootTask);

        // If Activity's launching into PiP, move the mStartActivity immediately to pinned mode.
        // Note that mStartActivity and source should be in the same Task at this point.
        if (mOptions != null && mOptions.isLaunchIntoPip()
                && sourceRecord != null && sourceRecord.getTask() == mStartActivity.getTask()
                && balCode != BAL_BLOCK) {
            mRootWindowContainer.moveActivityToPinnedRootTask(mStartActivity,
                    sourceRecord, "launch-into-pip");
        }

        return START_SUCCESS;
    }
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
  • setInitialState 方法用于初始化一堆参数
  • computeLaunchingTaskFlags 方法,根据 launchMode 和 Intent 中的 FLAG_ACTIVITY_NEW_TASK 等 flag 综合计算 activity 的启动模式,结果保存在 mLaunchFlags 中。计算的过程不仅要考虑目标 activity 的 launchMode,也要考虑原来 activity 的 launchMode 和 Intent 中所带着的 flag
  • 关注点 1 computeLaunchParams,计算启动参数,结果保存在 mLaunchParams 中
  • 关注点 2 getOrCreateRootTask ,用于创建一个 Task 对象,也就是目标 Task。Task 创建的时候就会挂载到窗口容器树中,也就是会挂载到DefaultTaskDisplayArea 下
  • 关注点 3 setNewTask(taskToAffiliate) ,其主要作用是把目标 ActivityRecord 插入新创建的 Task
  • 关注点 4 mTargetRootTask.getRootTask().moveToFront 移动新创建的 Task 到 TaskDisplayArea 的子节点的栈顶
  • 调用 grantUriPermissionUncheckedFromIntent 给目标 Activity 添加 uri 权限
  • 关注点 5 TargetRootTask.startActivityLocked:调整目标 Task 内部参数,开启转场动画(这个动画就是 App 开启时的白屏,在 Android 12 修改为 SplashScreen)为启动 Activity 做好准备
  • 关注点 6 resumeFocusedTasksTopActivities :生命周期处理

# 3. 核心要点分析

在了解了总体流程以后,接下来我们就来分析重要的几个关注点。

# 3.1 computeLaunchParams,计算启动参数

关注点 1 computeLaunchParams,计算启动参数,结果保存在 mLaunchParams 中:

// /frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
    
    private LaunchParams mLaunchParams = new LaunchParams();

    private void computeLaunchParams(ActivityRecord r, ActivityRecord sourceRecord,
            Task targetTask) {
        
        // 去计算启动相关的参数
        mSupervisor.getLaunchParamsController().calculate(targetTask, r.info.windowLayout, r,
                sourceRecord, mOptions, mRequest, PHASE_BOUNDS, mLaunchParams);

        mPreferredTaskDisplayArea = mLaunchParams.hasPreferredTaskDisplayArea()
                ? mLaunchParams.mPreferredTaskDisplayArea
                : mRootWindowContainer.getDefaultTaskDisplayArea();

        mPreferredWindowingMode = mLaunchParams.mWindowingMode;
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

主要关注一下 mPreferredTaskDisplayArea 这个参数,后面会用到。其值会通过 mRootWindowContainer.getDefaultTaskDisplayArea() 设置。

// /frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
    TaskDisplayArea getDefaultTaskDisplayArea() {
        return mDefaultDisplay.getDefaultTaskDisplayArea();
    }

// /frameworks/base/services/core/java/com/android/server/wm/DisplayContent.java
    TaskDisplayArea getDefaultTaskDisplayArea() {
        return mDisplayAreaPolicy.getDefaultTaskDisplayArea();
    }
1
2
3
4
5
6
7
8
9

这里会返回窗口容器树中的 defaultTaskDisplayArea。也就说 mPreferredTaskDisplayArea 的值是 defaultTaskDisplayArea

# 3.2 构建 Task 对象

关注点 2,getOrCreateRootTask 方法创建一个目标 Task 对象:

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

    private Task getOrCreateRootTask(ActivityRecord r, int launchFlags, Task task,
            ActivityOptions aOptions) {
        final boolean onTop =
                (aOptions == null || !aOptions.getAvoidMoveToFront()) && !mLaunchTaskBehind; // true
        final Task sourceTask = mSourceRecord != null ? mSourceRecord.getTask() : null; // QuickStepLauncher
        return mRootWindowContainer.getOrCreateRootTask(r, aOptions, task, sourceTask, onTop,
                mLaunchParams, launchFlags);
    }
1
2
3
4
5
6
7
8
9
10

RootWindowContainer 是 DisplayContent 的父节点。

在计算出两个参数 onTop 和 sourceTask 后,接着调用 getOrCreateRootTask 方法:

// frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
    Task getOrCreateRootTask(@Nullable ActivityRecord r,
            @Nullable ActivityOptions options, @Nullable Task candidateTask,
            @Nullable Task sourceTask, boolean onTop,
            @Nullable LaunchParamsController.LaunchParams launchParams, int launchFlags) {
      
        // ......

        TaskDisplayArea taskDisplayArea = null;
        if (launchParams != null && launchParams.mPreferredTaskDisplayArea != null) { // 进入
            taskDisplayArea = launchParams.mPreferredTaskDisplayArea; // 实际就是 DefaultTaskDisplayArea
        } else if (options != null) { // 不进入
           //......
        }

        final int activityType = resolveActivityType(r, options, candidateTask); // 1
        if (taskDisplayArea != null) {
            if (canLaunchOnDisplay(r, taskDisplayArea.getDisplayId())) { // 进入
                // 直接返回了
                return taskDisplayArea.getOrCreateRootTask(r, options, candidateTask,
                        sourceTask, launchParams, launchFlags, activityType, onTop);
            } else {
                taskDisplayArea = null;
            }
        }

       // ......
    }
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

接着调用 taskDisplayArea.getOrCreateRootTask 方法:

// frameworks/base/services/core/java/com/android/server/wm/TaskDisplayArea.java
    Task getOrCreateRootTask(@Nullable ActivityRecord r, @Nullable ActivityOptions options,
            @Nullable Task candidateTask, @Nullable Task sourceTask,
            @Nullable LaunchParams launchParams, int launchFlags, int activityType, boolean onTop) {
        int windowingMode = WINDOWING_MODE_UNDEFINED;
        if (launchParams != null) {
            // If launchParams isn't null, windowing mode is already resolved.
            windowingMode = launchParams.mWindowingMode;
        } else if (options != null) {
            // If launchParams is null and options isn't let's use the windowing mode in the
            // options.
            windowingMode = options.getLaunchWindowingMode();
        }
        // Validate that our desired windowingMode will work under the current conditions.
        // UNDEFINED windowing mode is a valid result and means that the new root task will inherit
        // it's display's windowing mode.
        windowingMode = validateWindowingMode(windowingMode, r, candidateTask); // 0

        return getOrCreateRootTask(windowingMode, activityType, onTop, candidateTask, sourceTask,
                options, launchFlags);
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

计算出 windowmode,当前情景下是 0(WINDOWING_MODE_UNDEFINED),接着调用另一个重载 getOrCreateRootTask:

// frameworks/base/services/core/java/com/android/server/wm/TaskDisplayArea.java
    Task getOrCreateRootTask(int windowingMode, int activityType, boolean onTop,
            @Nullable Task candidateTask, @Nullable Task sourceTask,
            @Nullable ActivityOptions options, int launchFlags) {
        final int resolvedWindowingMode =
                windowingMode == WINDOWING_MODE_UNDEFINED ? getWindowingMode() : windowingMode; // 1
        // .......
        return new Task.Builder(mAtmService)
                .setWindowingMode(windowingMode)
                .setActivityType(activityType)
                .setOnTop(onTop)
                .setParent(this)
                .setSourceTask(sourceTask)
                .setActivityOptions(options)
                .setLaunchFlags(launchFlags)
                .build();
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

最后,调用 Task.Builder 构建一个 Task 对象,需要注意的是,这里通过 setParent 将当前 DefaultTaskDisplayArea 对象设置为父节点,也就是说新创建的 Task 再初始化时就挂载到了窗口容器树中了

目标 Task 就创建好了,并且插入了窗口容器树中,成为了 TaskDisplayArea 的子节点。

# 3.3 把目标 ActivityRecord 插入新创建的 Task 中

接着我们看关注点 3, setNewTask(taskToAffiliate) 该方法的主要作用是把目标 ActivityRecord 插入新创建的 Task 中。

// frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
    private void setNewTask(Task taskToAffiliate) {
        final boolean toTop = !mLaunchTaskBehind && !mAvoidMoveToFront;
        // reuseOrCreateTask 实际就是返回之前新创建的 Task 对象
        final Task task = mTargetRootTask.reuseOrCreateTask(
                mStartActivity.info, mIntent, mVoiceSession,
                mVoiceInteractor, toTop, mStartActivity, mSourceRecord, mOptions);
        task.mTransitionController.collectExistenceChange(task);

        // addOrReparentStartingActivity 方法将目标 ActivityRecord 插入新创建的 Task 中
        addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask");

        ProtoLog.v(WM_DEBUG_TASKS, "Starting new activity %s in new task %s",
                mStartActivity, mStartActivity.getTask());

        if (taskToAffiliate != null) {
            mStartActivity.setTaskToAffiliateWith(taskToAffiliate);
        }
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

接着调用 addOrReparentStartingActivity 方法:

// frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java 
    private void addOrReparentStartingActivity(@NonNull Task task, String reason) {
        TaskFragment newParent = task; // 刚刚新创建的 Task
        if (mInTaskFragment != null) { // 不进入
           // ......
        } else {
            TaskFragment candidateTf = mAddingToTaskFragment != null ? mAddingToTaskFragment : null; // null
            if (candidateTf == null) { // 进入
                final ActivityRecord top = task.topRunningActivity(false /* focusableOnly */); // null
                if (top != null) {
                    candidateTf = top.getTaskFragment();
                }
            }
            if (candidateTf != null && candidateTf.isEmbedded()
                    && canEmbedActivity(candidateTf, mStartActivity, task) == EMBEDDING_ALLOWED) { // 不进入
                // Use the embedded TaskFragment of the top activity as the new parent if the
                // activity can be embedded.
                newParent = candidateTf;
            }
        }
        if (mStartActivity.getTaskFragment() == null
                || mStartActivity.getTaskFragment() == newParent) {
            //newParent 就是刚刚创建的 Task
            newParent.addChild(mStartActivity, POSITION_TOP);
        } else {
            mStartActivity.reparent(newParent, newParent.getChildCount() /* top */, reason);
        }
    }
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

我们接着看 addChild,addChild 实现在 Task 的父类 TaskFragment 中。

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

    // child 就是之前创建的目标 ActivityRecord
    // index:POSITION_TOP
    @Override
    void addChild(WindowContainer child, int index) {
        ActivityRecord r = topRunningActivity(); //null
        mClearedTaskForReuse = false;
        mClearedTaskFragmentForPip = false;
        mClearedForReorderActivityToFront = false;

        final ActivityRecord addingActivity = child.asActivityRecord();
        final boolean isAddingActivity = addingActivity != null;
        final Task task = isAddingActivity ? getTask() : null;

        // If this task had any activity before we added this one.
        boolean taskHadActivity = task != null && task.getTopMostActivity() != null;
        // getActivityType() looks at the top child, so we need to read the type before adding
        // a new child in case the new child is on top and UNDEFINED.
        final int activityType = task != null ? task.getActivityType() : ACTIVITY_TYPE_UNDEFINED;

        // 调用父类的 addChild
        super.addChild(child, index);

        if (isAddingActivity && task != null) {
            // TODO(b/207481538): temporary per-activity screenshoting
            if (r != null && BackNavigationController.isScreenshotEnabled()) {
                ProtoLog.v(WM_DEBUG_BACK_PREVIEW, "Screenshotting Activity %s",
                        r.mActivityComponent.flattenToString());
                Rect outBounds = r.getBounds();
                ScreenCapture.ScreenshotHardwareBuffer backBuffer = ScreenCapture.captureLayers(
                        r.mSurfaceControl,
                        new Rect(0, 0, outBounds.width(), outBounds.height()),
                        1f);
                mBackScreenshots.put(r.mActivityComponent.flattenToString(), backBuffer);
            }
            addingActivity.inHistory = true;
            task.onDescendantActivityAdded(taskHadActivity, activityType, addingActivity);
        }

        final WindowProcessController hostProcess = getOrganizerProcessIfDifferent(addingActivity);
        if (hostProcess != null) {
            hostProcess.addEmbeddedActivity(addingActivity);
        }
    }
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

接着调用父类 WindowContainer 的 addChild 方法:

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

    void addChild(E child, int index) {
        if (!child.mReparenting && child.getParent() != null) { // 不进入
            throw new IllegalArgumentException("addChild: container=" + child.getName()
                    + " is already a child of container=" + child.getParent().getName()
                    + " can't add to container=" + getName()
                    + "\n callers=" + Debug.getCallers(15, "\n"));
        }

        if ((index < 0 && index != POSITION_BOTTOM)
                || (index > mChildren.size() && index != POSITION_TOP)) { // 不进入
            throw new IllegalArgumentException("addChild: invalid position=" + index
                    + ", children number=" + mChildren.size());
        }

        if (index == POSITION_TOP) {
            index = mChildren.size();
        } else if (index == POSITION_BOTTOM) {
            index = 0;
        }

        //核心要点
        mChildren.add(index, child); // 添加到 Task 的子节点

        // Set the parent after we've actually added a child in case a subclass depends on this.
        child.setParent(this);
    }
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

核心的流程就是将 ActivityRecord 添加到 Task 的子节点 mChildren 中,设置 ActivityRecord 的父节点是 Task。

# 3.4 挂载新构建的 Task

关注点 4 mTargetRootTask.getRootTask().moveToFront 移动新创建的 Task 到 TaskDisplayArea 的子节点的栈顶,也就是把新构建的 Task 挂载到窗口容器树中。

    // frameworks/base/services/core/java/com/android/server/wm/Task.java
    void moveToFront(String reason, Task task) {
        if (!isAttached()) {
            return;
        }
        mTransitionController.recordTaskOrder(this);

        // 获取到 TaskDisplayArea 对象
        final TaskDisplayArea taskDisplayArea = getDisplayArea();

        if (!isActivityTypeHome() && returnsToHomeRootTask()) { // 不进入
            // Make sure the root home task is behind this root task since that is where we
            // should return to when this root task is no longer visible.
            taskDisplayArea.moveHomeRootTaskToFront(reason + " returnToHome");
        }

        // 就是新创建的 Task
        final Task lastFocusedTask = isRootTask() ? taskDisplayArea.getFocusedRootTask() : null;
        if (task == null) { // 进入,this 也是新创建的 Task
            task = this;
        }

        // 将新创建的 Task 放到 TaskDisplayArea 的子节点的栈顶
        task.getParent().positionChildAt(POSITION_TOP, task, true /* includingParents */);
        // 更新 mLastFocusedRootTask 的值
        taskDisplayArea.updateLastFocusedRootTask(lastFocusedTask, reason);
    }
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

# 3.5 显示启动 window

关注点 5 TargetRootTask.startActivityLocked:调整 Task 相关参数,显示启动 window(App 启动白屏),为启动 Activity 做好准备:

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

// r:目标 ActivityRecord 对象
    void startActivityLocked(ActivityRecord r, @Nullable Task topTask, boolean newTask,
            boolean isTaskSwitch, ActivityOptions options, @Nullable ActivityRecord sourceRecord) {
      
        // null
        final ActivityRecord pipCandidate = findEnterPipOnTaskSwitchCandidate(topTask);
        // 新创建的 Task 对象
        Task rTask = r.getTask();
        // true
        final boolean allowMoveToFront = options == null || !options.getAvoidMoveToFront();
        // false
        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.
            // 把 Task 放到父节点的栈顶,感觉这里有点重复了
            positionChildAtTop(rTask);
        }
        Task task = null;
        if (!newTask && isOrhasTask && !r.shouldBeVisible()) { // 不进入
            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
        final Task activityTask = r.getTask();

        // ......

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

        // ......

        final DisplayContent dc = mDisplayContent;
        if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
                "Prepare open transition: starting " + r);

        if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) { // 不进入
          // ......
        } else { // 进入
            dc.prepareAppTransition(TRANSIT_OPEN); // 准备过渡动画
            mTaskSupervisor.mNoAnimActivities.remove(r);
        }
        if (newTask && !r.mLaunchTaskBehind) { // 进入
            // If a new task is being launched, then mark the existing top activity as
            // supporting picture-in-picture while pausing only if the starting activity
            // would not be considered an overlay on top of the current activity
            // (eg. not fullscreen, or the assistant)
            enableEnterPipOnTaskSwitch(pipCandidate,
                    null /* toFrontTask */, r, options); // 多窗口相关的设置
        }
        boolean doShow = true;

        if (newTask) { // 进入
            // Even though this activity is starting fresh, we still need
            // to reset it to make sure we apply affinities to move any
            // existing activities from other tasks in to it.
            // If the caller has requested that the target task be
            // reset, then do so.
            if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) { // 进入
                resetTaskIfNeeded(r, r);
                doShow = topRunningNonDelayedActivityLocked(null) == r; // true
            }
        } else if (options != null && options.getAnimationType()
                == ActivityOptions.ANIM_SCENE_TRANSITION) {
            doShow = false;
        }

        // ......

        if (r.mLaunchTaskBehind) { // 不进入
           // ......
        } 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 baseTask = r.getTask();
            final ActivityRecord prev = baseTask.getActivity(
                    a -> a.mStartingData != null && a.showToCurrentUser());
            // 显示启动 window(App 启动白屏)
            mWmService.mStartingSurfaceController.showStartingWindow(r, prev, newTask,
                    isTaskSwitch, sourceRecord);
        }
    }
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
96

# 4. 总结

代码非常繁琐,总结一下,核心的要点其实不多:

  • 创建好目标 Task 对象
  • 将 Task 对象放到正确的位置
  • 显示启动 window(App 启动白屏)
  • 最后调用 RootWindowContainer.resumeFocusedTasksTopActivities 开启生命周期处理流程

# 参考资料