Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 251297b3 authored by Matt Sziklay's avatar Matt Sziklay Committed by Android (Google) Code Review
Browse files

Merge "Transition out of split screen when triggering enter desktop." into main

parents 2bda028d 0e6daf90
Loading
Loading
Loading
Loading
+11 −2
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@
package com.android.wm.shell.desktopmode

import android.app.ActivityManager.RunningTaskInfo
import android.app.WindowConfiguration
import android.app.WindowConfiguration.ACTIVITY_TYPE_HOME
import android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD
import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM
@@ -61,6 +60,7 @@ import com.android.wm.shell.desktopmode.DesktopModeTaskRepository.VisibleTasksLi
import com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.TO_DESKTOP_INDICATOR
import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE
import com.android.wm.shell.splitscreen.SplitScreenController
import com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_ENTER_DESKTOP
import com.android.wm.shell.sysui.ShellCommandHandler
import com.android.wm.shell.sysui.ShellController
import com.android.wm.shell.sysui.ShellInit
@@ -213,6 +213,7 @@ class DesktopTasksController(
            "DesktopTasksController: moveToDesktop taskId=%d",
            task.taskId
        )
        exitSplitIfApplicable(wct, task)
        // Bring other apps to front first
        bringDesktopAppsToFront(task.displayId, wct)
        addMoveToDesktopChanges(wct, task)
@@ -240,6 +241,7 @@ class DesktopTasksController(
            taskInfo.taskId
        )
        val wct = WindowContainerTransaction()
        exitSplitIfApplicable(wct, taskInfo)
        moveHomeTaskToFront(wct)
        addMoveToDesktopChanges(wct, taskInfo)
        wct.setBounds(taskInfo.token, startBounds)
@@ -319,7 +321,7 @@ class DesktopTasksController(
            task.taskId
        )
        val wct = WindowContainerTransaction()
        wct.setWindowingMode(task.token, WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW)
        wct.setWindowingMode(task.token, WINDOWING_MODE_MULTI_WINDOW)
        wct.setBounds(task.token, Rect())
        wct.setDensityDpi(task.token, getDefaultDensityDpi())
        if (Transitions.ENABLE_SHELL_TRANSITIONS) {
@@ -329,6 +331,13 @@ class DesktopTasksController(
        }
    }

    private fun exitSplitIfApplicable(wct: WindowContainerTransaction, taskInfo: RunningTaskInfo) {
        if (taskInfo.windowingMode == WINDOWING_MODE_MULTI_WINDOW) {
            splitScreenController.prepareExitSplitScreen(wct,
                splitScreenController.getStageOfTask(taskInfo.taskId), EXIT_REASON_ENTER_DESKTOP)
        }
    }

    /**
     * The second part of the animated move to desktop transition, called after
     * {@link startMoveToDesktop}. Move a task to fullscreen after being dragged from fullscreen
+4 −1
Original line number Diff line number Diff line
@@ -23,7 +23,6 @@ import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.RemoteAnimationTarget.MODE_OPENING;

import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
@@ -131,6 +130,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
    public static final int EXIT_REASON_CHILD_TASK_ENTER_PIP = 9;
    public static final int EXIT_REASON_RECREATE_SPLIT = 10;
    public static final int EXIT_REASON_FULLSCREEN_SHORTCUT = 11;
    public static final int EXIT_REASON_ENTER_DESKTOP = 12;
    @IntDef(value = {
            EXIT_REASON_UNKNOWN,
            EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW,
@@ -144,6 +144,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
            EXIT_REASON_CHILD_TASK_ENTER_PIP,
            EXIT_REASON_RECREATE_SPLIT,
            EXIT_REASON_FULLSCREEN_SHORTCUT,
            EXIT_REASON_ENTER_DESKTOP
    })
    @Retention(RetentionPolicy.SOURCE)
    @interface ExitReason{}
@@ -1011,6 +1012,8 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
                return "CHILD_TASK_ENTER_PIP";
            case EXIT_REASON_RECREATE_SPLIT:
                return "RECREATE_SPLIT";
            case EXIT_REASON_ENTER_DESKTOP:
                return "ENTER_DESKTOP";
            default:
                return "unknown reason, reason int = " + exitReason;
        }
+4 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED_
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__DEVICE_FOLDED;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__DRAG_DIVIDER;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__FULLSCREEN_SHORTCUT;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__ENTER_DESKTOP;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__RECREATE_SPLIT;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__RETURN_HOME;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__ROOT_TASK_VANISHED;
@@ -42,6 +43,7 @@ import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_CHILD_TASK_ENTER_PIP;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_DEVICE_FOLDED;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_DRAG_DIVIDER;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_ENTER_DESKTOP;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_FULLSCREEN_SHORTCUT;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_RECREATE_SPLIT;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_RETURN_HOME;
@@ -192,6 +194,8 @@ public class SplitscreenEventLogger {
                return SPLITSCREEN_UICHANGED__EXIT_REASON__RECREATE_SPLIT;
            case EXIT_REASON_FULLSCREEN_SHORTCUT:
                return SPLITSCREEN_UICHANGED__EXIT_REASON__FULLSCREEN_SHORTCUT;
            case EXIT_REASON_ENTER_DESKTOP:
                return SPLITSCREEN_UICHANGED__EXIT_REASON__ENTER_DESKTOP;
            case EXIT_REASON_UNKNOWN:
                // Fall through
            default:
+25 −8
Original line number Diff line number Diff line
@@ -68,6 +68,7 @@ import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.split.SplitScreenConstants.SplitPosition;
import com.android.wm.shell.desktopmode.DesktopModeStatus;
import com.android.wm.shell.desktopmode.DesktopTasksController;
import com.android.wm.shell.desktopmode.DesktopTasksController.SnapPosition;
@@ -348,13 +349,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
            final int id = v.getId();
            if (id == R.id.close_window || id == R.id.close_button) {
                mTaskOperations.closeTask(mTaskToken);
                if (mSplitScreenController != null
                        && mSplitScreenController.isSplitScreenVisible()) {
                    int remainingTaskPosition = mTaskId == mSplitScreenController
                            .getTaskInfo(SPLIT_POSITION_TOP_OR_LEFT).taskId
                            ? SPLIT_POSITION_BOTTOM_OR_RIGHT : SPLIT_POSITION_TOP_OR_LEFT;
                    ActivityManager.RunningTaskInfo remainingTask = mSplitScreenController
                            .getTaskInfo(remainingTaskPosition);
                if (isTaskInSplitScreen(mTaskId)) {
                    RunningTaskInfo remainingTask = getOtherSplitTask(mTaskId);
                    mSplitScreenController.moveTaskToFullscreen(remainingTask.taskId);
                }
                decoration.closeMaximizeMenu();
@@ -376,6 +372,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
                    mWindowDecorByTaskId.get(mTaskId).addCaptionInset(wct);
                    decoration.incrementRelayoutBlock();
                    mDesktopTasksController.get().moveToDesktop(decoration, mTaskId, wct);
                    closeOtherSplitTask(mTaskId);
                }
                decoration.closeHandleMenu();
            } else if (id == R.id.fullscreen_button) {
@@ -720,6 +717,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
                            relevantDecor.mTaskInfo.displayId);
                    if (ev.getY() > statusBarHeight) {
                        if (mMoveToDesktopAnimator == null) {
                            closeOtherSplitTask(relevantDecor.mTaskInfo.taskId);
                            mMoveToDesktopAnimator = new MoveToDesktopAnimator(
                                    mDragToDesktopAnimationStartBounds, relevantDecor.mTaskInfo,
                                    relevantDecor.mTaskSurface);
@@ -810,7 +808,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
    private DesktopModeWindowDecoration getRelevantWindowDecor(MotionEvent ev) {
        if (mSplitScreenController != null && mSplitScreenController.isSplitScreenVisible()) {
            // We can't look at focused task here as only one task will have focus.
            return getSplitScreenDecor(ev);
            DesktopModeWindowDecoration splitTaskDecor = getSplitScreenDecor(ev);
            return splitTaskDecor == null ? getFocusedDecor() : splitTaskDecor;
        } else {
            return getFocusedDecor();
        }
@@ -942,6 +941,24 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
        }
    }

    private RunningTaskInfo getOtherSplitTask(int taskId) {
        @SplitPosition int remainingTaskPosition = mSplitScreenController
                .getSplitPosition(taskId) == SPLIT_POSITION_BOTTOM_OR_RIGHT
                ? SPLIT_POSITION_TOP_OR_LEFT : SPLIT_POSITION_BOTTOM_OR_RIGHT;
        return mSplitScreenController.getTaskInfo(remainingTaskPosition);
    }

    private void closeOtherSplitTask(int taskId) {
        if (isTaskInSplitScreen(taskId)) {
            mTaskOperations.closeTask(getOtherSplitTask(taskId).token);
        }
    }

    private boolean isTaskInSplitScreen(int taskId) {
        return mSplitScreenController != null
                && mSplitScreenController.isTaskInSplitScreen(taskId);
    }

    private class DragStartListenerImpl
            implements DragPositioningCallbackUtility.DragStartListener {
        @Override
+35 −0
Original line number Diff line number Diff line
@@ -52,6 +52,8 @@ import com.android.wm.shell.common.SyncTransactionQueue
import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFreeformTask
import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFullscreenTask
import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createHomeTask
import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createSplitScreenTask
import com.android.wm.shell.splitscreen.SplitScreenController
import com.android.wm.shell.sysui.ShellCommandHandler
import com.android.wm.shell.sysui.ShellController
import com.android.wm.shell.sysui.ShellInit
@@ -94,6 +96,7 @@ class DesktopTasksControllerTest : ShellTestCase() {
            ToggleResizeDesktopTaskTransitionHandler
    @Mock lateinit var launchAdjacentController: LaunchAdjacentController
    @Mock lateinit var desktopModeWindowDecoration: DesktopModeWindowDecoration
    @Mock lateinit var splitScreenController: SplitScreenController

    private lateinit var mockitoSession: StaticMockitoSession
    private lateinit var controller: DesktopTasksController
@@ -116,6 +119,7 @@ class DesktopTasksControllerTest : ShellTestCase() {
        whenever(transitions.startTransition(anyInt(), any(), isNull())).thenAnswer { Binder() }

        controller = createController()
        controller.splitScreenController = splitScreenController

        shellInit.init()
    }
@@ -340,6 +344,30 @@ class DesktopTasksControllerTest : ShellTestCase() {
        }
    }

    @Test
    fun moveToDesktop_splitTaskExitsSplit() {
        var task = setUpSplitScreenTask()
        controller.moveToDesktop(desktopModeWindowDecoration, task)
        val wct = getLatestMoveToDesktopWct()
        assertThat(wct.changes[task.token.asBinder()]?.windowingMode)
            .isEqualTo(WINDOWING_MODE_FREEFORM)
        verify(splitScreenController).prepareExitSplitScreen(any(), anyInt(),
            eq(SplitScreenController.EXIT_REASON_ENTER_DESKTOP)
        )
    }

    @Test
    fun moveToDesktop_fullscreenTaskDoesNotExitSplit() {
        var task = setUpFullscreenTask()
        controller.moveToDesktop(desktopModeWindowDecoration, task)
        val wct = getLatestMoveToDesktopWct()
        assertThat(wct.changes[task.token.asBinder()]?.windowingMode)
            .isEqualTo(WINDOWING_MODE_FREEFORM)
        verify(splitScreenController, never()).prepareExitSplitScreen(any(), anyInt(),
            eq(SplitScreenController.EXIT_REASON_ENTER_DESKTOP)
        )
    }

    @Test
    fun moveToFullscreen_displayFullscreen_windowingModeSetToUndefined() {
        val task = setUpFreeformTask()
@@ -695,6 +723,13 @@ class DesktopTasksControllerTest : ShellTestCase() {
        return task
    }

    private fun setUpSplitScreenTask(displayId: Int = DEFAULT_DISPLAY): RunningTaskInfo {
        val task = createSplitScreenTask(displayId)
        whenever(shellTaskOrganizer.getRunningTaskInfo(task.taskId)).thenReturn(task)
        runningTasks.add(task)
        return task
    }

    private fun markTaskVisible(task: RunningTaskInfo) {
        desktopModeTaskRepository.updateVisibleFreeformTasks(
            task.displayId,
Loading