Android 12系统源码_分屏模式(一)从最近任务触发分屏模式

前言

打开MainActivity,然后进入最近任务触发分屏,可以成功进入分屏模式。

本篇文章我们来具体梳理一下这个过程的源码调用流程。

一 launcher3阶段

1.1 源码

java 复制代码
//packages/apps/Launcher3/quickstep/src/com/android/quickstep/views/TaskView.java
public class TaskView extends FrameLayout implements Reusable {
    private void onClick(View view) {
        if (getTask() == null) {
            return;
        }
        if (confirmSecondSplitSelectApp()) {
            return;
        }
        launchTasks();
        ...代码省略...
    }

    private boolean confirmSecondSplitSelectApp() {
        boolean isSelectingSecondSplitApp = getRecentsView().isSplitSelectionActive();
        if (isSelectingSecondSplitApp) {
            //调用RecentsView的confirmSplitSelect方法
            getRecentsView().confirmSplitSelect(this);
        }
        return isSelectingSecondSplitApp;
    }
}

//packages/apps/Launcher3/quickstep/src/com/android/quickstep/views/RecentsView.java
public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_TYPE>,
        STATE_TYPE extends BaseState<STATE_TYPE>> extends PagedView implements Insettable,
        TaskThumbnailCache.HighResLoadingState.HighResLoadingStateChangedCallback,
        TaskVisualsChangeListener {

    protected SplitSelectStateController mSplitSelectStateController;

    public void confirmSplitSelect(TaskView taskView) {
          ...代码省略...
        pendingAnimation.addEndListener(aBoolean -> {
                pendingAnimation.addEndListener(aBoolean ->
                //待动画结束,执行SplitSelectStateController的setSecondTaskId方法
                mSplitSelectStateController.setSecondTaskId(taskView.getTask(),
                aBoolean1 -> RecentsView.this.resetFromSplitSelectionState()));  
          ...代码省略...
    }
}

//packages/apps/Launcher3/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
public class SplitSelectStateController {

    public void setSecondTaskId(Task task, Consumer<Boolean> callback) {
        mSecondTask = task;
        launchTasks(mInitialTask, mSecondTask, mStagePosition, callback,
                false /* freezeTaskList */, DEFAULT_SPLIT_RATIO);
    }

    private final SystemUiProxy mSystemUiProxy;
    public void launchTasks(Task task1, Task task2, @StagePosition int stagePosition,
                            Consumer<Boolean> callback, boolean freezeTaskList, float splitRatio) {
        ...代码省略...
        mSystemUiProxy.startTasksWithLegacyTransition(taskIds[0], mainOpts.toBundle(),
                taskIds[1], null /* sideOptions */, STAGE_POSITION_BOTTOM_OR_RIGHT,
                splitRatio, adapter);    
         ...代码省略...
    }

}

//packages/apps/Launcher3/quickstep/src/com/android/quickstep/SystemUiProxy.java
public class SystemUiProxy implements ISystemUiProxy, NavHandle {
    private ISplitScreen mSplitScreen;

    public void startTasksWithLegacyTransition(int mainTaskId, Bundle mainOptions, int sideTaskId,
                                               Bundle sideOptions, @SplitConfigurationOptions.StagePosition int sidePosition,
                                               float splitRatio, RemoteAnimationAdapter adapter) {
        if (mSystemUiProxy != null) {
            try {
                mSplitScreen.startTasksWithLegacyTransition(mainTaskId, mainOptions, sideTaskId,
                        sideOptions, sidePosition, splitRatio, adapter);
            } catch (RemoteException e) {
                Log.w(TAG, "Failed call startTasksWithLegacyTransition");
            }
        }
    }
}

1.2 时序图

二 SystemUI阶段

2.1 源码

java 复制代码
public class SplitScreenController implements DragAndDropPolicy.Starter,
        RemoteCallable<SplitScreenController> {
    private static class ISplitScreenImpl extends ISplitScreen.Stub {
        @Override
        public void startTasksWithLegacyTransition(int mainTaskId, @Nullable Bundle mainOptions,
                                                   int sideTaskId, @Nullable Bundle sideOptions, @SplitPosition int sidePosition,
                                                   float splitRatio, RemoteAnimationAdapter adapter) {
            executeRemoteCallWithTaskPermission(mController, "startTasks",
                    (controller) -> controller.mStageCoordinator.startTasksWithLegacyTransition(
                            mainTaskId, mainOptions, sideTaskId, sideOptions, sidePosition,
                            splitRatio, adapter));
        }
    }
}

class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        RootTaskDisplayAreaOrganizer.RootTaskDisplayAreaListener, Transitions.TransitionHandler {

    private final ShellTaskOrganizer mTaskOrganizer;

    void startTasksWithLegacyTransition(int mainTaskId, @Nullable Bundle mainOptions,
                                        int sideTaskId, @Nullable Bundle sideOptions, @SplitPosition int sidePosition,
                                        float splitRatio, RemoteAnimationAdapter adapter) {
        //设置分割线的可见性
        setDividerVisibility(false /* visible */);
        //初始化分屏的分割线的布局
        mSplitLayout.init();
        // Set false to avoid record new bounds with old task still on top;
        mShouldUpdateRecents = false;
        final WindowContainerTransaction wct = new WindowContainerTransaction();
        final WindowContainerTransaction evictWct = new WindowContainerTransaction();
        prepareEvictChildTasks(SPLIT_POSITION_TOP_OR_LEFT, evictWct);
        prepareEvictChildTasks(SPLIT_POSITION_BOTTOM_OR_RIGHT, evictWct);
        //创建一个远程动画的回调binder对象
        IRemoteAnimationRunner wrapper = new IRemoteAnimationRunner.Stub() {
            @Override
            public void onAnimationStart(@WindowManager.TransitionOldType int transit,
                                         RemoteAnimationTarget[] apps,
                                         RemoteAnimationTarget[] wallpapers,
                                         RemoteAnimationTarget[] nonApps,
                                         final IRemoteAnimationFinishedCallback finishedCallback) {
                   ...代码省略...
            }

            @Override
            public void onAnimationCancelled() {
                   ...代码省略...
            }
        };
        //创建RemoteAnimationAdapter类型的远程动画
        RemoteAnimationAdapter wrappedAdapter = new RemoteAnimationAdapter(
                wrapper, adapter.getDuration(), adapter.getStatusBarTransitionDelay());
        if (mainOptions == null) {
            //构建出对应的mainOptions,及上分屏的启动option
            mainOptions = ActivityOptions.makeRemoteAnimation(wrappedAdapter).toBundle();
        } else {
            ActivityOptions mainActivityOptions = ActivityOptions.fromBundle(mainOptions);
            mainActivityOptions.update(ActivityOptions.makeRemoteAnimation(wrappedAdapter));
            mainOptions = mainActivityOptions.toBundle();
        }
        //准备好对应的sideOptions,下分屏的option
        sideOptions = sideOptions != null ? sideOptions : new Bundle();

        setSideStagePosition(sidePosition, wct);
        //设置分界线比例
        mSplitLayout.setDivideRatio(splitRatio);
        if (mMainStage.isActive()) {
            mMainStage.moveToTop(getMainStageBounds(), wct);
        } else {
            // Build a request WCT that will launch both apps such that task 0 is on the main stage
            // while task 1 is on the side stage.
            mMainStage.activate(getMainStageBounds(), wct, false /* reparent */);
        }
        mSideStage.moveToTop(getSideStageBounds(), wct);
        //准备好对应的option参数
        // Make sure the launch options will put tasks in the corresponding split roots
        addActivityOptions(mainOptions, mMainStage);
        addActivityOptions(sideOptions, mSideStage);
        // Add task launch requests
        wct.startTask(mainTaskId, mainOptions);//主分屏task
        wct.startTask(sideTaskId, sideOptions);//次分屏task

        //最后把前面准备好的参数统一apply到SystemServer里面
        mTaskOrganizer.applyTransaction(wct);
    }
}

2.2 时序图

三 SystemServer阶段

3.1 源码

java 复制代码
//frameworks/base/services/core/java/com/android/server/wm/WindowOrganizerController.java
public class ShellTaskOrganizer extends TaskOrganizer implements CompatUIController.CompatUICallback {
    //父类方法
    public void applyTransaction(@NonNull WindowContainerTransaction t) {
        try {
            if (!t.isEmpty()) {
                //调用ActivityTaskManagerService的getWindowOrganizerController方法得到WindowOrganizerController对象
                //并调用WindowOrganizerController对象的applyTransaction方法
                getWindowOrganizerController().applyTransaction(t);
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    static IWindowOrganizerController getWindowOrganizerController() {
        return IWindowOrganizerControllerSingleton.get();
    }

    private static final Singleton<IWindowOrganizerController> IWindowOrganizerControllerSingleton =
            new Singleton<IWindowOrganizerController>() {
                @Override
                protected IWindowOrganizerController create() {
                    try {
                        return ActivityTaskManager.getService().getWindowOrganizerController();
                    } catch (RemoteException e) {
                        return null;
                    }
                }
            };
}

public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
    WindowOrganizerController mWindowOrganizerController;

    @Override
    public IWindowOrganizerController getWindowOrganizerController() {
        return mWindowOrganizerController;
    }
}

//base/services/core/java/com/android/server/wm/WindowOrganizerController.java
class WindowOrganizerController extends IWindowOrganizerController.Stub {

    @Override
    public void applyTransaction(WindowContainerTransaction t) {
        ...代码省略...
        applyTransaction(t, -1 /*syncId*/, null /*transition*/, caller);
        ...代码省略...
    }

    private void applyTransaction(@NonNull WindowContainerTransaction t, int syncId,
                                  @Nullable Transition transition, @NonNull CallerInfo caller) {
        ...代码省略...
        ArraySet<WindowContainer> haveConfigChanges = new ArraySet<>();
        //获取WindowContainerTransaction的change部分
        Iterator<Map.Entry<IBinder, WindowContainerTransaction.Change>> entries =
                t.getChanges().entrySet().iterator();
        while (entries.hasNext()) {//遍历每个变化的元素
            final Map.Entry<IBinder, WindowContainerTransaction.Change> entry = entries.next();
            final WindowContainer wc = WindowContainer.fromBinder(entry.getKey());
            if (wc == null || !wc.isAttached()) {
                Slog.e(TAG, "Attempt to operate on detached container: " + wc);
                continue;
            }
            // Make sure we add to the syncSet before performing
            // operations so we don't end up splitting effects between the WM
            // pending transaction and the BLASTSync transaction.
            if (syncId >= 0) {
                addToSyncSet(syncId, wc);
            }
            if (transition != null) transition.collect(wc);
            //注释1,这里一般就是前面说过的上屏和下屏的对应Task,调用applyWindowContainerChange方法进行对应处理
            int containerEffect = applyWindowContainerChange(wc, entry.getValue());
            effects |= containerEffect;

            // Lifecycle changes will trigger ensureConfig for everything.
            if ((effects & TRANSACT_EFFECTS_LIFECYCLE) == 0
                    && (containerEffect & TRANSACT_EFFECTS_CLIENT_CONFIG) != 0) {
                haveConfigChanges.add(wc);
            }
        }
        // Hierarchy changes
        final List<WindowContainerTransaction.HierarchyOp> hops = t.getHierarchyOps();
        final int hopSize = hops.size();
        if (hopSize > 0) {
            final boolean isInLockTaskMode = mService.isInLockTaskMode();
            for (int i = 0; i < hopSize; ++i) {
                //注释2,调用applyHierarchyOp方法,对reorder和starTask的操作进行处理
                effects |= applyHierarchyOp(hops.get(i), effects, syncId, transition,
                        isInLockTaskMode, caller, t.getErrorCallbackToken(),
                        t.getTaskFragmentOrganizer());
            }
        } 
        ...代码省略...
    }

    private int applyWindowContainerChange(WindowContainer wc, WindowContainerTransaction.Change c) {
        sanitizeWindowContainer(wc);
        //调用applyChanges
        int effects = applyChanges(wc, c);
        if (wc instanceof DisplayArea) {
            effects |= applyDisplayAreaChanges(wc.asDisplayArea(), c);
        } else if (wc instanceof Task) {
            effects |= applyTaskChanges(wc.asTask(), c);
        }
        return effects;
    }

    private int applyChanges(WindowContainer container, WindowContainerTransaction.Change change) {
        ...代码省略...
        //最重要就是获取change的configration,因为bounds变化被包在了configration里面,
        //这里再调用container的进行通知configration的变化
        final Configuration c =
                new Configuration(container.getRequestedOverrideConfiguration());
        c.setTo(change.getConfiguration(), configMask, windowMask);
        //Task容器调用这个onRequestedOverrideConfigurationChanged,
        //代表根据传递过来的Configration作为自己的覆盖变化,即也就把对应的bounds设置给了Task
        container.onRequestedOverrideConfigurationChanged(c);
        ...代码省略...
    }
}

调用applyHierarchyOp方法将task放到最上层

java 复制代码
class WindowOrganizerController extends IWindowOrganizerController.Stub {

    //HIERARCHY_OP_TYPE_REORDER和HIERARCHY_OP_TYPE_REPARENT类型
    private int applyHierarchyOp(WindowContainerTransaction.HierarchyOp hop, int effects,
                                 int syncId, @Nullable Transition transition, boolean isInLockTaskMode,
                                 @NonNull CallerInfo caller, @Nullable IBinder errorCallbackToken,
                                 @Nullable ITaskFragmentOrganizer organizer) {
        final int type = hop.getType();
        ...代码省略...
        switch (type) {
                ...代码省略...
            case HIERARCHY_OP_TYPE_REORDER:
            case HIERARCHY_OP_TYPE_REPARENT: {
                //首先要从hop中获取出WindowContainer
                final WindowContainer wc = WindowContainer.fromBinder(hop.getContainer());
                ...代码省略...
                //调用sanitizeAndApplyHierarchyOp进行处理
                effects |= sanitizeAndApplyHierarchyOp(wc, hop);
                break;
            }
            case HIERARCHY_OP_TYPE_LAUNCH_TASK: {
        	...代码省略...
            return effects;
        }

        private int sanitizeAndApplyHierarchyOp (WindowContainer container,
                WindowContainerTransaction.HierarchyOp hop){
            //这里获取task,其实就是RootTask,分屏最顶端那个taskId为4的
            final Task task = container.asTask();
            ...代码省略...
            //需要把task进行移动放到所有task的顶端位置
            task.getParent().positionChildAt(
                    hop.getToTop() ? POSITION_TOP : POSITION_BOTTOM,
                    task, false /* includingParents */);
            ...代码省略...
            return TRANSACT_EFFECTS_LIFECYCLE;

        }
    }

调用applyHierarchyOp方法对数据进行拆解,然后调用ActivityTaskSupervisor的startActivityFromRecents方法:

java 复制代码
class WindowOrganizerController extends IWindowOrganizerController.Stub {

    //HIERARCHY_OP_TYPE_REORDER和HIERARCHY_OP_TYPE_REPARENT类型
    private int applyHierarchyOp(WindowContainerTransaction.HierarchyOp hop, int effects,
                                 int syncId, @Nullable Transition transition, boolean isInLockTaskMode,
                                 @NonNull CallerInfo caller, @Nullable IBinder errorCallbackToken,
                                 @Nullable ITaskFragmentOrganizer organizer) {
        final int type = hop.getType();
        ...代码省略...
        switch (type) {
            ...代码省略...
            case HIERARCHY_OP_TYPE_REORDER:
            case HIERARCHY_OP_TYPE_REPARENT: 
            ...代码省略...
            case HIERARCHY_OP_TYPE_LAUNCH_TASK: {
                mService.mAmInternal.enforceCallingPermission(START_TASKS_FROM_RECENTS,
                        "launchTask HierarchyOp");
                final Bundle launchOpts = hop.getLaunchOptions();
                final int taskId = launchOpts.getInt(
                        WindowContainerTransaction.HierarchyOp.LAUNCH_KEY_TASK_ID);
                launchOpts.remove(WindowContainerTransaction.HierarchyOp.LAUNCH_KEY_TASK_ID);
                final SafeActivityOptions safeOptions =
                        SafeActivityOptions.fromBundle(launchOpts, caller.mPid, caller.mUid);
                final Integer[] starterResult = {null};
                // startActivityFromRecents should not be called in lock.
                mService.mH.post(() -> {
                    try {
                        //调用ActivityTaskSupervisor的startActivityFromRecents方法
                        starterResult[0] = mService.mTaskSupervisor.startActivityFromRecents(
                                caller.mPid, caller.mUid, taskId, safeOptions);
                    } catch (Throwable t) {
                        starterResult[0] = ActivityManager.START_CANCELED;
                        Slog.w(TAG, t);
                    }
                    synchronized (mGlobalLock) {
                        mGlobalLock.notifyAll();
                    }
                });
                while (starterResult[0] == null) {
                    try {
                        mGlobalLock.wait();
                    } catch (InterruptedException ignored) {
                    }
                }
                break;
            }
            ...代码省略...
            return effects;
        }
    }
}
//base/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
    
    	RootWindowContainer mRootWindowContainer;
    	final ActivityTaskManagerService mService;

        int startActivityFromRecents(int callingPid, int callingUid, int taskId,
                                     SafeActivityOptions options) {
            final Task task;
            final int taskCallingUid;
            final String callingPackage;
            final String callingFeatureId;
            final Intent intent;
            final int userId;
            final ActivityOptions activityOptions = options != null
                    ? options.getOptions(this)
                    : null;
            boolean moveHomeTaskForward = true;
            synchronized (mService.mGlobalLock) {
                int activityType = ACTIVITY_TYPE_UNDEFINED;
                if (activityOptions != null) {
                    activityType = activityOptions.getLaunchActivityType();
                ...代码省略...
                    //这里主要通过taskId来获取一个Task,但是这个方法不仅仅只干了获取task的事情,
                    //还干了把taskId对应的Task进行reparent到新上下分屏的容器Task,这样实现了层级结构树上面的挂载完成,
                    //剩下就是一系列操作来保证Activiyt生命周期正常相关
                    task = mRootWindowContainer.anyTaskForId(taskId,
                            MATCH_ATTACHED_TASK_OR_RECENT_TASKS_AND_RESTORE, activityOptions, ON_TOP);
                ...代码省略...
                    if (!mService.mAmInternal.shouldConfirmCredentials(task.mUserId)
                            && task.getRootActivity() != null) {
                        //获取task的Activity
                        final ActivityRecord targetActivity = task.getTopNonFinishingActivity();
                    ...代码省略...
                    	//调用
                        mService.moveTaskToFrontLocked(null /* appThread */,
                                null /* callingPackage */, task.mTaskId, 0, options);
                    ...代码省略...
                    }
                }
            }
        }
    }
}

RootWindowContainer的anyTaskForId方法

java 复制代码
class RootWindowContainer extends WindowContainer<DisplayContent>
        implements DisplayManager.DisplayListener {

    Task anyTaskForId(int id, @RootWindowContainer.AnyTaskForIdMatchTaskMode int matchMode,
                      @Nullable ActivityOptions aOptions, boolean onTop) {


        final PooledPredicate p = PooledLambda.obtainPredicate(
                Task::isTaskId, PooledLambda.__(Task.class), id);
        Task task = getTask(p);//遍历获取Task
        p.recycle();

        if (task != null) {
            if (aOptions != null) {//注意这里aOptions不为null,而且携带了task
                //这里有调用了getOrCreateRootTask来获取targetRootTask
                final Task targetRootTask =
                        getOrCreateRootTask(null, aOptions, task, onTop);
                if (targetRootTask != null && task.getRootTask() != targetRootTask) {
                    final int reparentMode = onTop
                            ? REPARENT_MOVE_ROOT_TASK_TO_FRONT : REPARENT_LEAVE_ROOT_TASK_IN_PLACE;
                    task.reparent(targetRootTask, onTop, reparentMode, ANIMATE, DEFER_RESUME,
                            "anyTaskForId");
                }
            }
            return task;
        }

        //省略
    }

    Task getOrCreateRootTask(@Nullable ActivityRecord r,
                             @Nullable ActivityOptions options, @Nullable Task candidateTask,
                             @Nullable Task sourceTask, boolean onTop,
                             @Nullable LaunchParamsController.LaunchParams launchParams, int launchFlags) {
        // First preference goes to the launch root task set in the activity options.
        if (options != null) {
            //这里终于体现systemui传递的mainoptions作用了
            final Task candidateRoot = Task.fromWindowContainerToken(options.getLaunchRootTask());
            if (candidateRoot != null && canLaunchOnDisplay(r, candidateRoot)) {
                return candidateRoot;//大家看这里就直接返回了options带的task
            }
        }
        //省略
    }
    
}

ActivityTaskManagerService的moveTaskToFrontLocked方法

java 复制代码
public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
    void moveTaskToFrontLocked(@Nullable IApplicationThread appThread,
                               @Nullable String callingPackage, int taskId, int flags, SafeActivityOptions options) {
        //省略
        try {
            final Task task = mRootWindowContainer.anyTaskForId(taskId);
            //省略
            ActivityOptions realOptions = options != null
                    ? options.getOptions(mTaskSupervisor)
                    : null;
            //这方法最为关键,寻找到task而且移到最前端
            mTaskSupervisor.findTaskToMoveToFront(task, flags, realOptions, "moveTaskToFront",
                    false /* forceNonResizable */);

            //开始启动StartingWindow
            final ActivityRecord topActivity = task.getTopNonFinishingActivity();
            if (topActivity != null) {

                // We are reshowing a task, use a starting window to hide the initial draw delay
                // so the transition can start earlier.
                topActivity.showStartingWindow(true /* taskSwitch */);
            }
            //省略
        }
    }
}

findTaskToMoveToFront方法

java 复制代码
public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
    /** This doesn't just find a task, it also moves the task to front. */
    void findTaskToMoveToFront(Task task, int flags, ActivityOptions options, String reason,
                               boolean forceNonResizeable) {
        //这里currentRootTask就是taskId =4的根task
        Task currentRootTask = task.getRootTask();
        //省略
        final ActivityRecord r = task.getTopNonFinishingActivity();
        //这里又调用到了关键moveTaskToFront方法
        currentRootTask.moveTaskToFront(task, false /* noAnimation */, options,
                r == null ? null : r.appTimeTracker, reason);

        //省略
    }

    final void moveTaskToFront(Task tr, boolean noAnimation, ActivityOptions options,
                               AppTimeTracker timeTracker, boolean deferResume, String reason) {
        //省略
        //这里又关键调用到了顶部ActivityRecord的moveFocusableActivityToTop方法
        // Set focus to the top running activity of this task and move all its parents to top.
        top.moveFocusableActivityToTop(reason);
        //省略
        if (!deferResume) {//进行对应resume操作
            mRootWindowContainer.resumeFocusedTasksTopActivities();
        }
        //省略
    }

    boolean moveFocusableActivityToTop(String reason) {

        final Task rootTask = getRootTask();
        //这里调用了rootTask把当前app的task移到最前
        rootTask.moveToFront(reason, task);
        // Report top activity change to tracking services and WM
        if (mRootWindowContainer.getTopResumedActivity() == this) { //注意这里可能大家有疑问为啥都可以getTopResumedActivity到了,还需要设置,那是因为getTopResumedActivity可能真正ResumedActivity为null,但是会通过获取getFocusedActivity获取作为ResumedActivity
            //这个操作关键,把ActivityRecord开始要变成Resumed状态了,这个就不展开,前面课程视频讲解
            mAtmService.setResumedActivityUncheckLocked(this, reason);
        }
        return true;
    }

    @Nullable
    ActivityRecord getTopResumedActivity() {
        final Task focusedRootTask = getTopDisplayFocusedRootTask();
        //getTopResumedActivity这个时候是为null哦
        final ActivityRecord resumedActivity = focusedRootTask.getTopResumedActivity();
        if (resumedActivity != null && resumedActivity.app != null) {
            return resumedActivity;
        }
        // The top focused root task might not have a resumed activity yet - look on all displays in
        // focus order.
        //前面发现为null后就获取getFocusedActivity
        return getItemFromTaskDisplayAreas(TaskDisplayArea::getFocusedActivity);
    }
}

3.2 时序图