android T分屏流程

概览

在这里插入图片描述
在这里插入图片描述
分屏前的order

  Task display areas in top down Z order:
    TaskDisplayArea DefaultTaskDisplayArea
      mPreferredTopFocusableRootTask=Task{919dc1b #1 type=home ?? U=0 visible=true visibleRequested=true mode=fullscreen translucent=false sz=1}
      mLastFocusedRootTask=Task{919dc1b #1 type=home ?? U=0 visible=true visibleRequested=true mode=fullscreen translucent=false sz=1}
      Application tokens in top down Z order:
      * Task{919dc1b #1 type=home ?? U=0 visible=true visibleRequested=true mode=fullscreen translucent=false sz=1}
        bounds=[0,0][1080,2520]
        * Task{95cd9f8 #2 type=home I=com.miui.home/.launcher.Launcher U=0 rootTaskId=1 visible=true visibleRequested=true mode=fullscreen translucent=false sz=1}
          bounds=[0,0][1080,2520]
          * ActivityRecord{23a7bec u0 com.miui.home/.launcher.Launcher} t2}
      * Task{e49cf5a #27 type=standard A=10219:com.miui.weather2 U=0 visible=false visibleRequested=false mode=fullscreen translucent=true sz=1}
        bounds=[0,0][1080,2520]
        * ActivityRecord{4788499 u0 com.miui.weather2/.ActivityWeatherMain} t27}
      * Task{ec94c1a #38 type=undefined ?? U=0 visible=false visibleRequested=false mode=fullscreen translucent=true sz=0}
        bounds=[0,0][1080,2520]
      * Task{a07962f #25 type=standard A=10070:android.task.mms U=0 visible=false visibleRequested=false mode=fullscreen translucent=true sz=1}
        bounds=[0,0][1080,2520]
        * ActivityRecord{43f400e u0 com.android.mms/.ui.MmsTabActivity} t25}
    // 分屏的Task位于TaskDisplayArea的最底部
      * Task{bcbb9ca #39 type=standard ?? U=0 visible=false visibleRequested=false mode=fullscreen translucent=true sz=2}
        bounds=[0,0][1080,2520]
        * Task{495d73b #41 type=standard ?? U=0 rootTaskId=39 visible=false visibleRequested=false mode=multi-window translucent=true sz=0}
          bounds=[0,1317][1080,2520]
        * Task{65e6135 #40 type=undefined ?? U=0 rootTaskId=39 visible=false visibleRequested=false mode=multi-window translucent=true sz=0}
          bounds=[0,0][1080,1289]

分屏时的order

  Task display areas in top down Z order:
    TaskDisplayArea DefaultTaskDisplayArea
      mPreferredTopFocusableRootTask=Task{f555c62 #4 type=standard ?? U=0 visible=true visibleRequested=true mode=fullscreen translucent=false sz=2}
      mLastFocusedRootTask=Task{f555c62 #4 type=standard ?? U=0 visible=true visibleRequested=true mode=fullscreen translucent=false sz=2}
      Application tokens in top down Z order:
      // reorder分屏相关Task到TaskDisplayArea顶部
      * Task{f555c62 #4 type=standard ?? U=0 visible=true visibleRequested=true mode=fullscreen translucent=false sz=2}
        bounds=[0,0][1080,2520]
        * Task{f4a61f3 #6 type=undefined ?? U=0 rootTaskId=4 visible=true visibleRequested=true mode=multi-window translucent=false sz=1}
          bounds=[0,1295][1080,2520]
          * Task{9b3720c #80 type=standard A=10213:com.miui.notes U=0 rootTaskId=4 visible=true visibleRequested=true mode=multi-window translucent=false sz=1}
            bounds=[0,1295][1080,2520]
            * ActivityRecord{2ab7e0 u0 com.miui.notes/.ui.NotesListActivity} t80}
        * Task{3c50f2d #5 type=standard ?? U=0 rootTaskId=4 visible=true visibleRequested=true mode=multi-window translucent=false sz=1}
          bounds=[0,0][1080,1267]
          * Task{27d1129 #78 type=undefined A=10003:com.miui.gallery.home U=0 rootTaskId=4 visible=true visibleRequested=true mode=multi-window translucent=false sz=2}
            bounds=[0,0][1080,1267]
            * ActivityRecord{c63706 u0 com.miui.gallery/.activity.GallerySettingsActivity} t78}
            * ActivityRecord{1435ba u0 com.miui.gallery/.activity.HomePageActivity} t78}
      * Task{a48f388 #1 type=home ?? U=0 visible=false visibleRequested=false mode=fullscreen translucent=true sz=1}
        bounds=[0,0][1080,2520]
        * Task{e676dd2 #2 type=home I=com.miui.home/.launcher.Launcher U=0 rootTaskId=1 visible=false visibleRequested=false mode=fullscreen translucent=true sz=1}
          bounds=[0,0][1080,2520]
          * ActivityRecord{3faca81 u0 com.miui.home/.launcher.Launcher} t2}
      * Task{ad9de1e #3 type=undefined ?? U=0 visible=false visibleRequested=false mode=fullscreen translucent=true sz=0}
        bounds=[0,0][1080,2520]

进入分屏

systemui 进程

android T上的分屏是在分屏下屏确定后桌面进程调用位于systemui进程的wm shell下的com.android.wm.shell.splitscreen.SplitScreenController.ISplitScreenImpl的startTasksWithLegacyTransition方法去开启分屏流程。

    /**
     * The interface for calls from outside the host process.
     */
    @BinderThread
    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) {
            // binder 线程post 到主线程的executor去执行
            executeRemoteCallWithTaskPermission(mController, "startTasks",
                    (controller) -> controller.mStageCoordinator.startTasksWithLegacyTransition(
                            mainTaskId, mainOptions, sideTaskId, sideOptions, sidePosition,
                            splitRatio, adapter));
        }

system server进程

进入分屏时WindowContainerTransaction的HierarchyOp列表包含三个元素:reorder、startTask、startTask
在这里插入图片描述

    private void applyTransaction(@NonNull WindowContainerTransaction t, int syncId,
            @Nullable Transition transition, @NonNull CallerInfo caller,
            @Nullable Transition finishTransition) {
            ......
            // 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) {
                    effects |= applyHierarchyOp(hops.get(i), effects, syncId, transition,
                            isInLockTaskMode, caller, t.getErrorCallbackToken(),
                            t.getTaskFragmentOrganizer(), finishTransition);
                }
            }
           ......
    }

在这里插入图片描述

退出分屏

systemui进程

在这里插入图片描述

system server进程

退出分屏时WindowContainerTransaction的HierarchyOp列表也包含三个元素:childrenTasksReparent、childrenTasksReparent、reorder(分屏最外层的fullcscreen task)
在这里插入图片描述

{ChildrenTasksReparent: from=RemoteToken{6206d89 Task{495d73b #41 type=standard ?? U=0 rootTaskId=39 visible=true visibleRequested=true mode=multi-window translucent=false sz=1}} to=null mToTop=false mReparentTopOnly=false mWindowingMode=[1, 0, 6] mActivityType=[1]}
{ChildrenTasksReparent: from=RemoteToken{1d0a090 Task{65e6135 #40 type=undefined ?? U=0 rootTaskId=39 visible=true visibleRequested=true mode=multi-window translucent=false sz=1}} to=null mToTop=true mReparentTopOnly=false mWindowingMode=[1, 0, 6] mActivityType=[1]}
{reorder: RemoteToken{aae4b1a Task{bcbb9ca #39 type=standard ?? U=0 visible=true visibleRequested=true mode=fullscreen translucent=false sz=2}} to bottom}

在这里插入图片描述

    private int reparentChildrenTasksHierarchyOp(WindowContainerTransaction.HierarchyOp hop,
            @Nullable Transition transition, int syncId) {
        // 一般为分屏的上下屏Task,mode为multi-window
        WindowContainer<?> currentParent = hop.getContainer() != null
                ? WindowContainer.fromBinder(hop.getContainer()) : null;
        // 这里一般为null
        WindowContainer newParent = hop.getNewParent() != null
                ? WindowContainer.fromBinder(hop.getNewParent()) : null;
        if (currentParent == null && newParent == null) {
            throw new IllegalArgumentException("reparentChildrenTasksHierarchyOp: " + hop);
        } else if (currentParent == null) {
            currentParent = newParent.asTask().getDisplayContent().getDefaultTaskDisplayArea();
        } else if (newParent == null) {
            // newParent赋值为TaskDisplayArea
            newParent = currentParent.asTask().getDisplayContent().getDefaultTaskDisplayArea();
        }

       ......

        // We want to collect the tasks first before re-parenting to avoid array shifting on us.
        final ArrayList<Task> tasksToReparent = new ArrayList<>();

        currentParent.forAllTasks(task -> {
            Slog.i(TAG, " Processing task=" + task);
            final boolean reparent;
            if (task.mCreatedByOrganizer || task.getParent() != finalCurrentParent) {
                // We only care about non-organized task that are direct children of the thing we
                // are reparenting from.
                return false;
            }
            if (newParentInMultiWindow && !task.supportsMultiWindowInDisplayArea(newParentTda)) {
                Slog.e(TAG, "reparentChildrenTasksHierarchyOp non-resizeable task to multi window,"
                        + " task=" + task);
                return false;
            }
            if (!ArrayUtils.contains(hop.getActivityTypes(), task.getActivityType())
                    || !ArrayUtils.contains(hop.getWindowingModes(), task.getWindowingMode())) {
                return false;
            }

            if (hop.getToTop()) {
                tasksToReparent.add(0, task);
            } else {
                tasksToReparent.add(task);
            }
            return hop.getReparentTopOnly() && tasksToReparent.size() == 1;
        });

        final int count = tasksToReparent.size();
        for (int i = 0; i < count; ++i) {
            final Task task = tasksToReparent.get(i);
            if (syncId >= 0) {
                addToSyncSet(syncId, task);
            }
            if (transition != null) transition.collect(task);
        	// 执行reparent操作
            if (newParent instanceof TaskDisplayArea) {
                // For now, reparenting to display area is different from other reparents...
                task.reparent((TaskDisplayArea) newParent, hop.getToTop());
            } else {
                task.reparent((Task) newParent,
                        hop.getToTop() ? POSITION_TOP : POSITION_BOTTOM,
                        false /*moveParents*/, "processChildrenTaskReparentHierarchyOp");
            }
        }

        if (transition != null) transition.collect(newParent);

        return TRANSACT_EFFECTS_LIFECYCLE;
    }
Android 7.0(API 级别 24)及以上的系统支持分屏功能,可以同时显示两个应用程序的界面,提高多任务处理效率。下面是 Android 分屏的基本流程: 1. 判断是否支持分屏功能: 在应用程序的代码中,可以通过以下方式判断当前设备是否支持分屏功能: ```java if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { // 支持分屏功能 } else { // 不支持分屏功能 } ``` 2. 请求分屏权限: 在 AndroidManifest.xml 文件中添加以下权限: ```xml <uses-permission android:name="android.permission.REQUEST_SPLIT_SCREEN" /> ``` 然后在代码中调用以下方法请求分屏权限: ```java if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { if (!isInMultiWindowMode()) { boolean isSplitScreenSupported = requestSplitScreenPermission(); if (!isSplitScreenSupported) { // 设备不支持分屏功能 } } } ``` 3. 进入分屏模式: 在代码中调用以下方法可以进入分屏模式: ```java if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { if (isInMultiWindowMode()) { // 已经在分屏模式下 } else { enterPictureInPictureMode(); } } ``` 4. 离开分屏模式: 在代码中调用以下方法可以离开分屏模式: ```java if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { if (isInMultiWindowMode()) { exitPictureInPictureMode(); } else { // 不在分屏模式下 } } ``` 注意:进入分屏模式和离开分屏模式可以通过用户手动拖动应用程序窗口边缘来实现,也可以通过代码来实现。在进入和离开分屏模式时,应用程序需要进行相应的布局调整,以适应不同的屏幕尺寸。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值