diff options
6 files changed, 99 insertions, 18 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt index 40c519eb0d5a..55d21481be0b 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt @@ -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 diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java index 991b699161ea..f70b0fc5af48 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java @@ -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;          } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitscreenEventLogger.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitscreenEventLogger.java index 5483fa5d29f6..f4ab2266179a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitscreenEventLogger.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitscreenEventLogger.java @@ -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: diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java index abd2ad49317b..012433d05fa8 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java @@ -21,7 +21,6 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;  import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;  import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;  import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; -  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;  import static com.android.wm.shell.desktopmode.EnterDesktopTaskTransitionHandler.FINAL_FREEFORM_SCALE; @@ -69,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 +348,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 +371,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 +716,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 +807,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 +940,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 diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt index be4a287bff9d..c6cccc059e89 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt @@ -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()      } @@ -341,6 +345,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()          task.configuration.windowConfiguration.displayWindowingMode = WINDOWING_MODE_FULLSCREEN @@ -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, diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTestHelpers.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTestHelpers.kt index 29a757c19d98..2f6f3207137d 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTestHelpers.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTestHelpers.kt @@ -21,6 +21,7 @@ import android.app.WindowConfiguration.ACTIVITY_TYPE_HOME  import android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD  import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM  import android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN +import android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW  import android.view.Display.DEFAULT_DISPLAY  import com.android.wm.shell.MockToken  import com.android.wm.shell.TestRunningTaskInfoBuilder @@ -45,12 +46,25 @@ class DesktopTestHelpers {          @JvmOverloads          fun createFullscreenTask(displayId: Int = DEFAULT_DISPLAY): RunningTaskInfo {              return TestRunningTaskInfoBuilder() -                    .setDisplayId(displayId) -                    .setToken(MockToken().token()) -                    .setActivityType(ACTIVITY_TYPE_STANDARD) -                    .setWindowingMode(WINDOWING_MODE_FULLSCREEN) -                    .setLastActiveTime(100) -                    .build() +                .setDisplayId(displayId) +                .setToken(MockToken().token()) +                .setActivityType(ACTIVITY_TYPE_STANDARD) +                .setWindowingMode(WINDOWING_MODE_FULLSCREEN) +                .setLastActiveTime(100) +                .build() +        } + +        /** Create a task that has windowing mode set to [WINDOWING_MODE_MULTI_WINDOW] */ +        @JvmStatic +        @JvmOverloads +        fun createSplitScreenTask(displayId: Int = DEFAULT_DISPLAY): RunningTaskInfo { +            return TestRunningTaskInfoBuilder() +                .setDisplayId(displayId) +                .setToken(MockToken().token()) +                .setActivityType(ACTIVITY_TYPE_STANDARD) +                .setWindowingMode(WINDOWING_MODE_MULTI_WINDOW) +                .setLastActiveTime(100) +                .build()          }          /** Create a new home task */  |