summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Treehugger Robot <android-test-infra-autosubmit@system.gserviceaccount.com> 2025-02-24 12:03:24 -0800
committer Android (Google) Code Review <android-gerrit@google.com> 2025-02-24 12:03:24 -0800
commitdd407c456f20dd1fbe5286cda0288a2e0513279d (patch)
treec640e2ce139f52b08f73ea01ad7aea0f9d305f50
parent56d5b3753b4fb67d9ae4103d41af861f4a590b0b (diff)
parent160e43beeb3e6ee9555b31f71c4012865448e8e5 (diff)
Merge "[23/N] Desks: Deactivate desk when moving to split-screen" into main
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt34
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java8
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java14
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt25
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java73
5 files changed, 137 insertions, 17 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 2d9aea014fbe..180d069f359d 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
@@ -2701,10 +2701,12 @@ class DesktopTasksController(
/**
* Adds split screen changes to a transaction. Note that bounds are not reset here due to
* animation; see {@link onDesktopSplitSelectAnimComplete}
- *
- * TODO: b/394268248 - desk needs to be deactivated.
*/
- private fun addMoveToSplitChanges(wct: WindowContainerTransaction, taskInfo: RunningTaskInfo) {
+ private fun addMoveToSplitChanges(
+ wct: WindowContainerTransaction,
+ taskInfo: RunningTaskInfo,
+ deskId: Int?,
+ ): RunOnTransitStart? {
// This windowing mode is to get the transition animation started; once we complete
// split select, we will change windowing mode to undefined and inherit from split stage.
// Going to undefined here causes task to flicker to the top left.
@@ -2714,11 +2716,12 @@ class DesktopTasksController(
// want it overridden in multi-window.
wct.setDensityDpi(taskInfo.token, getDefaultDensityDpi())
- performDesktopExitCleanupIfNeeded(
+ return performDesktopExitCleanupIfNeeded(
taskId = taskInfo.taskId,
displayId = taskInfo.displayId,
+ deskId = deskId,
wct = wct,
- forceToFullscreen = false,
+ forceToFullscreen = true,
shouldEndUpAtHome = false,
)
}
@@ -2950,14 +2953,21 @@ class DesktopTasksController(
}
dragToDesktopTransitionHandler.cancelDragToDesktopTransition(cancelState)
} else {
+ val deskId = taskRepository.getDeskIdForTask(taskInfo.taskId)
+ logV("Split requested for task=%d in desk=%d", taskInfo.taskId, deskId)
val wct = WindowContainerTransaction()
- addMoveToSplitChanges(wct, taskInfo)
- splitScreenController.requestEnterSplitSelect(
- taskInfo,
- wct,
- if (leftOrTop) SPLIT_POSITION_TOP_OR_LEFT else SPLIT_POSITION_BOTTOM_OR_RIGHT,
- taskInfo.configuration.windowConfiguration.bounds,
- )
+ val runOnTransitStart = addMoveToSplitChanges(wct, taskInfo, deskId)
+ val transition =
+ splitScreenController.requestEnterSplitSelect(
+ taskInfo,
+ wct,
+ if (leftOrTop) SPLIT_POSITION_TOP_OR_LEFT
+ else SPLIT_POSITION_BOTTOM_OR_RIGHT,
+ taskInfo.configuration.windowConfiguration.bounds,
+ )
+ if (transition != null) {
+ runOnTransitStart?.invoke(transition)
+ }
}
}
}
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 ba30d924e0b1..10b23fd2f552 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
@@ -54,6 +54,7 @@ import android.content.pm.ShortcutInfo;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Handler;
+import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.ArrayMap;
@@ -580,10 +581,13 @@ public class SplitScreenController implements SplitDragPolicy.Starter,
* @param wct transaction to apply if this is a valid request
* @param splitPosition the split position this task should move to
* @param taskBounds current freeform bounds of the task entering split
+ *
+ * @return the token of the transition that started as a result of entering split select.
*/
- public void requestEnterSplitSelect(ActivityManager.RunningTaskInfo taskInfo,
+ @Nullable
+ public IBinder requestEnterSplitSelect(ActivityManager.RunningTaskInfo taskInfo,
WindowContainerTransaction wct, int splitPosition, Rect taskBounds) {
- mStageCoordinator.requestEnterSplitSelect(taskInfo, wct, splitPosition, taskBounds);
+ return mStageCoordinator.requestEnterSplitSelect(taskInfo, wct, splitPosition, taskBounds);
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 77a7c5406a67..0438d16796cf 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -122,6 +122,7 @@ import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
import android.view.WindowManager;
import android.widget.Toast;
+import android.window.DesktopExperienceFlags;
import android.window.DisplayAreaInfo;
import android.window.RemoteTransition;
import android.window.TransitionInfo;
@@ -219,6 +220,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
private final Context mContext;
private final List<SplitScreen.SplitScreenListener> mListeners = new ArrayList<>();
private final Set<SplitScreen.SplitSelectListener> mSelectListeners = new HashSet<>();
+ private final Transitions mTransitions;
private final DisplayController mDisplayController;
private final DisplayImeController mDisplayImeController;
private final DisplayInsetsController mDisplayInsetsController;
@@ -419,6 +421,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
iconProvider,
mWindowDecorViewModel, STAGE_TYPE_SIDE);
}
+ mTransitions = transitions;
mDisplayController = displayController;
mDisplayImeController = displayImeController;
mDisplayInsetsController = displayInsetsController;
@@ -455,6 +458,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mTaskOrganizer = taskOrganizer;
mMainStage = mainStage;
mSideStage = sideStage;
+ mTransitions = transitions;
mDisplayController = displayController;
mDisplayImeController = displayImeController;
mDisplayInsetsController = displayInsetsController;
@@ -660,16 +664,22 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
return mLogger;
}
- void requestEnterSplitSelect(ActivityManager.RunningTaskInfo taskInfo,
+ @Nullable
+ IBinder requestEnterSplitSelect(ActivityManager.RunningTaskInfo taskInfo,
WindowContainerTransaction wct, int splitPosition, Rect taskBounds) {
boolean enteredSplitSelect = false;
for (SplitScreen.SplitSelectListener listener : mSelectListeners) {
enteredSplitSelect |= listener.onRequestEnterSplitSelect(taskInfo, splitPosition,
taskBounds);
}
- if (enteredSplitSelect) {
+ if (!enteredSplitSelect) {
+ return null;
+ }
+ if (!DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue()) {
mTaskOrganizer.applyTransaction(wct);
+ return null;
}
+ return mTransitions.startTransition(TRANSIT_CHANGE, wct, /* handler= */ null);
}
void startShortcut(String packageName, String shortcutId, @SplitPosition int position,
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 93eb396742ab..ac1deec53bf6 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
@@ -5249,6 +5249,24 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
}
@Test
+ @EnableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND)
+ fun enterSplit_wasInDesk_deactivatesDesk() {
+ val deskId = 5
+ taskRepository.addDesk(displayId = DEFAULT_DISPLAY, deskId = deskId)
+ taskRepository.setActiveDesk(displayId = DEFAULT_DISPLAY, deskId = deskId)
+ val task = setUpFreeformTask(displayId = DEFAULT_DISPLAY, deskId = deskId)
+ val transition = Binder()
+ whenever(splitScreenController.requestEnterSplitSelect(eq(task), any(), any(), any()))
+ .thenReturn(transition)
+
+ controller.requestSplit(task, leftOrTop = false)
+
+ verify(desksOrganizer).deactivateDesk(any(), eq(deskId))
+ verify(desksTransitionsObserver)
+ .addPendingTransition(DeskTransition.DeactivateDesk(transition, deskId))
+ }
+
+ @Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MULTI_INSTANCE_FEATURES)
fun newWindow_fromFullscreenOpensInSplit() {
setUpLandscapeDisplay()
@@ -6601,6 +6619,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
bounds: Rect? = null,
active: Boolean = true,
background: Boolean = false,
+ deskId: Int? = null,
): RunningTaskInfo {
val task = createFreeformTask(displayId, bounds)
val activityInfo = ActivityInfo()
@@ -6613,7 +6632,11 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
} else {
whenever(shellTaskOrganizer.getRunningTaskInfo(task.taskId)).thenReturn(task)
}
- taskRepository.addTask(displayId, task.taskId, isVisible = active)
+ if (deskId != null) {
+ taskRepository.addTaskToDesk(displayId, deskId, task.taskId, isVisible = active)
+ } else {
+ taskRepository.addTask(displayId, task.taskId, isVisible = active)
+ }
if (!background) {
runningTasks.add(task)
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
index 10c28626dc9f..e9c4c31729e9 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
@@ -38,6 +38,8 @@ import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -48,6 +50,7 @@ import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -58,6 +61,7 @@ import android.app.ActivityOptions;
import android.app.PendingIntent;
import android.content.res.Configuration;
import android.graphics.Rect;
+import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
@@ -196,6 +200,7 @@ public class StageCoordinatorTests extends ShellTestCase {
when(token.asBinder()).thenReturn(mBinder);
when(mRunningTaskInfo.getToken()).thenReturn(token);
when(mTaskOrganizer.getRunningTaskInfo(mTaskId)).thenReturn(mRunningTaskInfo);
+ when(mTaskOrganizer.startNewTransition(anyInt(), any())).thenReturn(new Binder());
when(mRootTDAOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY)).thenReturn(mDisplayAreaInfo);
when(mSplitLayout.getTopLeftBounds()).thenReturn(mBounds1);
@@ -557,6 +562,60 @@ public class StageCoordinatorTests extends ShellTestCase {
assertFalse(c != null && c.getWindowingMode() == WINDOWING_MODE_FULLSCREEN);
}
+ @Test
+ @DisableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND)
+ public void testRequestEnterSplit_didNotEnterSplitSelect_doesNotApplyTransaction() {
+ final WindowContainerTransaction wct = new WindowContainerTransaction();
+ mStageCoordinator.registerSplitSelectListener(
+ new TestSplitSelectListener(/* alwaysEnter = */ false));
+
+ final IBinder transition = mStageCoordinator.requestEnterSplitSelect(mRunningTaskInfo, wct,
+ SPLIT_POSITION_TOP_OR_LEFT, new Rect(0, 0, 100, 100));
+
+ assertNull(transition);
+ verify(mTaskOrganizer, never()).applyTransaction(wct);
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND)
+ public void testRequestEnterSplit_enteredSplitSelect_appliesTransaction() {
+ final WindowContainerTransaction wct = new WindowContainerTransaction();
+ mStageCoordinator.registerSplitSelectListener(
+ new TestSplitSelectListener(/* alwaysEnter = */ true));
+
+ final IBinder transition = mStageCoordinator.requestEnterSplitSelect(mRunningTaskInfo, wct,
+ SPLIT_POSITION_TOP_OR_LEFT, new Rect(0, 0, 100, 100));
+
+ assertNull(transition);
+ verify(mTaskOrganizer).applyTransaction(wct);
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND)
+ public void testRequestEnterSplit_didNotEnterSplitSelect_doesNotStartTransition() {
+ final WindowContainerTransaction wct = new WindowContainerTransaction();
+ mStageCoordinator.registerSplitSelectListener(
+ new TestSplitSelectListener(/* alwaysEnter = */ false));
+
+ final IBinder transition = mStageCoordinator.requestEnterSplitSelect(mRunningTaskInfo, wct,
+ SPLIT_POSITION_TOP_OR_LEFT, new Rect(0, 0, 100, 100));
+
+ assertNull(transition);
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND)
+ public void testRequestEnterSplit_enteredSplitSelect_startsTransition() {
+ final WindowContainerTransaction wct = new WindowContainerTransaction();
+ mStageCoordinator.registerSplitSelectListener(
+ new TestSplitSelectListener(/* alwaysEnter = */ true));
+
+ final IBinder transition = mStageCoordinator.requestEnterSplitSelect(mRunningTaskInfo, wct,
+ SPLIT_POSITION_TOP_OR_LEFT, new Rect(0, 0, 100, 100));
+
+ assertNotNull(transition);
+ }
+
private Transitions createTestTransitions() {
ShellInit shellInit = new ShellInit(mMainExecutor);
final Transitions t = new Transitions(mContext, shellInit, mock(ShellController.class),
@@ -566,4 +625,18 @@ public class StageCoordinatorTests extends ShellTestCase {
shellInit.init();
return t;
}
+
+ private static class TestSplitSelectListener implements SplitScreen.SplitSelectListener {
+ private final boolean mAlwaysEnter;
+
+ TestSplitSelectListener(boolean alwaysEnter) {
+ mAlwaysEnter = alwaysEnter;
+ }
+
+ @Override
+ public boolean onRequestEnterSplitSelect(ActivityManager.RunningTaskInfo taskInfo,
+ int splitPosition, Rect taskBounds) {
+ return mAlwaysEnter;
+ }
+ }
}