summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java6
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java164
2 files changed, 103 insertions, 67 deletions
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 6f7d992683cf..aff21cbe0ae6 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
@@ -34,6 +34,7 @@ import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static android.window.TransitionInfo.FLAG_IS_DISPLAY;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REORDER;
+import static com.android.window.flags.Flags.enableFullScreenWindowOnRemovingSplitScreenStageBugfix;
import static com.android.window.flags.Flags.enableNonDefaultDisplaySplit;
import static com.android.wm.shell.Flags.enableFlexibleSplit;
import static com.android.wm.shell.Flags.enableFlexibleTwoAppSplit;
@@ -908,6 +909,11 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
}
options = options != null ? options : new Bundle();
addActivityOptions(options, null);
+ ActivityManager.RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(taskId);
+ if (enableFullScreenWindowOnRemovingSplitScreenStageBugfix() && taskInfo != null
+ && taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM) {
+ prepareTasksForSplitScreen(new int[] {taskId}, wct);
+ }
wct.startTask(taskId, options);
mSplitTransitions.startFullscreenTransition(wct, remoteTransition);
}
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 5851cbf9b933..10c28626dc9f 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
@@ -22,6 +22,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.view.Display.DEFAULT_DISPLAY;
+import static com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_2_50_50;
import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_INDEX_UNDEFINED;
import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
@@ -61,6 +62,9 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
import android.view.SurfaceControl;
import android.window.DisplayAreaInfo;
import android.window.RemoteTransition;
@@ -71,6 +75,8 @@ import androidx.test.annotation.UiThreadTest;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
+import com.android.internal.logging.InstanceId;
+import com.android.window.flags.Flags;
import com.android.wm.shell.MockToken;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.ShellTaskOrganizer;
@@ -96,6 +102,7 @@ import com.android.wm.shell.transition.HomeTransitionObserver;
import com.android.wm.shell.transition.Transitions;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -111,6 +118,9 @@ import java.util.function.Consumer;
@SmallTest
@RunWith(AndroidJUnit4.class)
public class StageCoordinatorTests extends ShellTestCase {
+ @Rule
+ public final SetFlagsRule setFlagsRule = new SetFlagsRule();
+
@Mock
private ShellTaskOrganizer mTaskOrganizer;
@Mock
@@ -141,12 +151,15 @@ public class StageCoordinatorTests extends ShellTestCase {
private final Rect mBounds1 = new Rect(10, 20, 30, 40);
private final Rect mBounds2 = new Rect(5, 10, 15, 20);
private final Rect mRootBounds = new Rect(0, 0, 45, 60);
+ private final int mTaskId = 18;
- private SurfaceControl mRootLeash;
- private SurfaceControl mDividerLeash;
private ActivityManager.RunningTaskInfo mRootTask;
private StageCoordinator mStageCoordinator;
- private Transitions mTransitions;
+ private SplitScreenTransitions mSplitScreenTransitions;
+ private SplitScreenListener mSplitScreenListener;
+ private IBinder mBinder;
+ private ActivityManager.RunningTaskInfo mRunningTaskInfo;
+ private RemoteTransition mRemoteTransition;
private final TestShellExecutor mMainExecutor = new TestShellExecutor();
private final ShellExecutor mAnimExecutor = new TestShellExecutor();
private final Handler mMainHandler = new Handler(Looper.getMainLooper());
@@ -154,19 +167,35 @@ public class StageCoordinatorTests extends ShellTestCase {
DEFAULT_DISPLAY, 0);
private final ActivityManager.RunningTaskInfo mMainChildTaskInfo =
new TestRunningTaskInfoBuilder().setVisible(true).build();
+ private final ArgumentCaptor<WindowContainerTransaction> mWctCaptor =
+ ArgumentCaptor.forClass(WindowContainerTransaction.class);
+ private final WindowContainerTransaction mWct = spy(new WindowContainerTransaction());
@Before
@UiThreadTest
public void setup() {
MockitoAnnotations.initMocks(this);
- mTransitions = createTestTransitions();
+ Transitions transitions = createTestTransitions();
+ WindowContainerToken token = mock(WindowContainerToken.class);
+ SurfaceControl dividerLeash = new SurfaceControl.Builder().setName("fakeDivider").build();
+
mStageCoordinator = spy(new StageCoordinator(mContext, DEFAULT_DISPLAY, mSyncQueue,
mTaskOrganizer, mMainStage, mSideStage, mDisplayController, mDisplayImeController,
- mDisplayInsetsController, mSplitLayout, mTransitions, mTransactionPool,
+ mDisplayInsetsController, mSplitLayout, transitions, mTransactionPool,
mMainExecutor, mMainHandler, Optional.empty(), mLaunchAdjacentController,
Optional.empty(), mSplitState, Optional.empty(), mRootTDAOrganizer));
-
- mDividerLeash = new SurfaceControl.Builder().setName("fakeDivider").build();
+ mSplitScreenTransitions = spy(mStageCoordinator.getSplitTransitions());
+ mSplitScreenListener = mock(SplitScreenListener.class);
+ mStageCoordinator.setSplitTransitions(mSplitScreenTransitions);
+ mBinder = mock(IBinder.class);
+ mRunningTaskInfo = mock(ActivityManager.RunningTaskInfo.class);
+ mRemoteTransition = mock(RemoteTransition.class);
+ mRunningTaskInfo.token = token;
+
+ when(mRemoteTransition.getDebugName()).thenReturn("");
+ when(token.asBinder()).thenReturn(mBinder);
+ when(mRunningTaskInfo.getToken()).thenReturn(token);
+ when(mTaskOrganizer.getRunningTaskInfo(mTaskId)).thenReturn(mRunningTaskInfo);
when(mRootTDAOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY)).thenReturn(mDisplayAreaInfo);
when(mSplitLayout.getTopLeftBounds()).thenReturn(mBounds1);
@@ -174,11 +203,11 @@ public class StageCoordinatorTests extends ShellTestCase {
when(mSplitLayout.getRootBounds()).thenReturn(mRootBounds);
when(mSplitLayout.isLeftRightSplit()).thenReturn(false);
when(mSplitLayout.applyTaskChanges(any(), any(), any())).thenReturn(true);
- when(mSplitLayout.getDividerLeash()).thenReturn(mDividerLeash);
+ when(mSplitLayout.getDividerLeash()).thenReturn(dividerLeash);
mRootTask = new TestRunningTaskInfoBuilder().build();
- mRootLeash = new SurfaceControl.Builder().setName("test").build();
- mStageCoordinator.onTaskAppeared(mRootTask, mRootLeash);
+ SurfaceControl rootLeash = new SurfaceControl.Builder().setName("test").build();
+ mStageCoordinator.onTaskAppeared(mRootTask, rootLeash);
mSideStage.mRootTaskInfo = new TestRunningTaskInfoBuilder().build();
mMainStage.mRootTaskInfo = new TestRunningTaskInfoBuilder().build();
@@ -196,14 +225,12 @@ public class StageCoordinatorTests extends ShellTestCase {
public void testMoveToStage_splitActiveBackground() {
when(mStageCoordinator.isSplitActive()).thenReturn(true);
- final ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder().build();
- final WindowContainerTransaction wct = spy(new WindowContainerTransaction());
+ mStageCoordinator.moveToStage(mRootTask, SPLIT_POSITION_BOTTOM_OR_RIGHT, mWct);
- mStageCoordinator.moveToStage(task, SPLIT_POSITION_BOTTOM_OR_RIGHT, wct);
// TODO(b/349828130) Address this once we remove index_undefined called
- verify(mStageCoordinator).prepareEnterSplitScreen(eq(wct), eq(task),
+ verify(mStageCoordinator).prepareEnterSplitScreen(eq(mWct), eq(mRootTask),
eq(SPLIT_POSITION_BOTTOM_OR_RIGHT), eq(false), eq(SPLIT_INDEX_UNDEFINED));
- verify(mMainStage).reparentTopTask(eq(wct));
+ verify(mMainStage).reparentTopTask(eq(mWct));
assertEquals(SPLIT_POSITION_BOTTOM_OR_RIGHT, mStageCoordinator.getSideStagePosition());
assertEquals(SPLIT_POSITION_TOP_OR_LEFT, mStageCoordinator.getMainStagePosition());
}
@@ -215,25 +242,21 @@ public class StageCoordinatorTests extends ShellTestCase {
// Assume current side stage is top or left.
mStageCoordinator.setSideStagePosition(SPLIT_POSITION_TOP_OR_LEFT, null);
- final ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder().build();
- final WindowContainerTransaction wct = new WindowContainerTransaction();
+ mStageCoordinator.moveToStage(mRootTask, SPLIT_POSITION_BOTTOM_OR_RIGHT, mWct);
- mStageCoordinator.moveToStage(task, SPLIT_POSITION_BOTTOM_OR_RIGHT, wct);
// TODO(b/349828130) Address this once we remove index_undefined called
- verify(mStageCoordinator).prepareEnterSplitScreen(eq(wct), eq(task),
+ verify(mStageCoordinator).prepareEnterSplitScreen(eq(mWct), eq(mRootTask),
eq(SPLIT_POSITION_BOTTOM_OR_RIGHT), eq(false), eq(SPLIT_INDEX_UNDEFINED));
assertEquals(SPLIT_POSITION_BOTTOM_OR_RIGHT, mStageCoordinator.getMainStagePosition());
assertEquals(SPLIT_POSITION_TOP_OR_LEFT, mStageCoordinator.getSideStagePosition());
}
@Test
- public void testMoveToStage_splitInctive() {
- final ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder().build();
- final WindowContainerTransaction wct = new WindowContainerTransaction();
+ public void testMoveToStage_splitInactive() {
+ mStageCoordinator.moveToStage(mRootTask, SPLIT_POSITION_BOTTOM_OR_RIGHT, mWct);
- mStageCoordinator.moveToStage(task, SPLIT_POSITION_BOTTOM_OR_RIGHT, wct);
// TODO(b/349828130) Address this once we remove index_undefined called
- verify(mStageCoordinator).prepareEnterSplitScreen(eq(wct), eq(task),
+ verify(mStageCoordinator).prepareEnterSplitScreen(eq(mWct), eq(mRootTask),
eq(SPLIT_POSITION_BOTTOM_OR_RIGHT), eq(false), eq(SPLIT_INDEX_UNDEFINED));
assertEquals(SPLIT_POSITION_BOTTOM_OR_RIGHT, mStageCoordinator.getSideStagePosition());
}
@@ -248,25 +271,23 @@ public class StageCoordinatorTests extends ShellTestCase {
@Test
public void testLayoutChanged_topLeftSplitPosition_updatesUnfoldStageBounds() {
mStageCoordinator.setSideStagePosition(SPLIT_POSITION_TOP_OR_LEFT, null);
- final SplitScreenListener listener = mock(SplitScreenListener.class);
- mStageCoordinator.registerSplitScreenListener(listener);
- clearInvocations(listener);
+ mStageCoordinator.registerSplitScreenListener(mSplitScreenListener);
+ clearInvocations(mSplitScreenListener);
mStageCoordinator.onLayoutSizeChanged(mSplitLayout);
- verify(listener).onSplitBoundsChanged(mRootBounds, mBounds2, mBounds1);
+ verify(mSplitScreenListener).onSplitBoundsChanged(mRootBounds, mBounds2, mBounds1);
}
@Test
public void testLayoutChanged_bottomRightSplitPosition_updatesUnfoldStageBounds() {
mStageCoordinator.setSideStagePosition(SPLIT_POSITION_BOTTOM_OR_RIGHT, null);
- final SplitScreenListener listener = mock(SplitScreenListener.class);
- mStageCoordinator.registerSplitScreenListener(listener);
- clearInvocations(listener);
+ mStageCoordinator.registerSplitScreenListener(mSplitScreenListener);
+ clearInvocations(mSplitScreenListener);
mStageCoordinator.onLayoutSizeChanged(mSplitLayout);
- verify(listener).onSplitBoundsChanged(mRootBounds, mBounds1, mBounds2);
+ verify(mSplitScreenListener).onSplitBoundsChanged(mRootBounds, mBounds1, mBounds2);
}
@Test
@@ -367,13 +388,8 @@ public class StageCoordinatorTests extends ShellTestCase {
@Test
public void testSplitIntentAndTaskWithPippedApp_launchFullscreen() {
int taskId = 9;
- SplitScreenTransitions splitScreenTransitions =
- spy(mStageCoordinator.getSplitTransitions());
- mStageCoordinator.setSplitTransitions(splitScreenTransitions);
mStageCoordinator.setMixedHandler(mDefaultMixedHandler);
PendingIntent pendingIntent = mock(PendingIntent.class);
- RemoteTransition remoteTransition = mock(RemoteTransition.class);
- when(remoteTransition.getDebugName()).thenReturn("");
// Test launching second task full screen
when(mDefaultMixedHandler.isIntentInPip(pendingIntent)).thenReturn(true);
mStageCoordinator.startIntentAndTask(
@@ -384,9 +400,9 @@ public class StageCoordinatorTests extends ShellTestCase {
null /*option2*/,
0 /*splitPosition*/,
1 /*snapPosition*/,
- remoteTransition /*remoteTransition*/,
+ mRemoteTransition /*remoteTransition*/,
null /*instanceId*/);
- verify(splitScreenTransitions, times(1))
+ verify(mSplitScreenTransitions, times(1))
.startFullscreenTransition(any(), any());
// Test launching first intent fullscreen
@@ -400,22 +416,17 @@ public class StageCoordinatorTests extends ShellTestCase {
null /*option2*/,
0 /*splitPosition*/,
1 /*snapPosition*/,
- remoteTransition /*remoteTransition*/,
+ mRemoteTransition /*remoteTransition*/,
null /*instanceId*/);
- verify(splitScreenTransitions, times(2))
+ verify(mSplitScreenTransitions, times(2))
.startFullscreenTransition(any(), any());
}
@Test
public void testSplitIntentsWithPippedApp_launchFullscreen() {
- SplitScreenTransitions splitScreenTransitions =
- spy(mStageCoordinator.getSplitTransitions());
- mStageCoordinator.setSplitTransitions(splitScreenTransitions);
mStageCoordinator.setMixedHandler(mDefaultMixedHandler);
PendingIntent pendingIntent = mock(PendingIntent.class);
PendingIntent pendingIntent2 = mock(PendingIntent.class);
- RemoteTransition remoteTransition = mock(RemoteTransition.class);
- when(remoteTransition.getDebugName()).thenReturn("");
// Test launching second task full screen
when(mDefaultMixedHandler.isIntentInPip(pendingIntent)).thenReturn(true);
mStageCoordinator.startIntents(
@@ -429,9 +440,9 @@ public class StageCoordinatorTests extends ShellTestCase {
new Bundle(),
0 /*splitPosition*/,
1 /*snapPosition*/,
- remoteTransition /*remoteTransition*/,
+ mRemoteTransition /*remoteTransition*/,
null /*instanceId*/);
- verify(splitScreenTransitions, times(1))
+ verify(mSplitScreenTransitions, times(1))
.startFullscreenTransition(any(), any());
// Test launching first intent fullscreen
@@ -448,35 +459,54 @@ public class StageCoordinatorTests extends ShellTestCase {
new Bundle(),
0 /*splitPosition*/,
1 /*snapPosition*/,
- remoteTransition /*remoteTransition*/,
+ mRemoteTransition /*remoteTransition*/,
null /*instanceId*/);
- verify(splitScreenTransitions, times(2))
+ verify(mSplitScreenTransitions, times(2))
.startFullscreenTransition(any(), any());
}
-
@Test
public void startTask_ensureWindowingModeCleared() {
- SplitScreenTransitions splitScreenTransitions =
- spy(mStageCoordinator.getSplitTransitions());
- mStageCoordinator.setSplitTransitions(splitScreenTransitions);
- ArgumentCaptor<WindowContainerTransaction> wctCaptor =
- ArgumentCaptor.forClass(WindowContainerTransaction.class);
- int taskId = 18;
- IBinder binder = mock(IBinder.class);
- ActivityManager.RunningTaskInfo rti = mock(ActivityManager.RunningTaskInfo.class);
- WindowContainerToken mockToken = mock(WindowContainerToken.class);
- when(mockToken.asBinder()).thenReturn(binder);
- when(rti.getToken()).thenReturn(mockToken);
- when(mTaskOrganizer.getRunningTaskInfo(taskId)).thenReturn(rti);
- mStageCoordinator.startTask(taskId, SPLIT_POSITION_TOP_OR_LEFT, null /*options*/,
+ mStageCoordinator.startTask(mTaskId, SPLIT_POSITION_TOP_OR_LEFT, null /*options*/,
null, SPLIT_INDEX_UNDEFINED);
- verify(splitScreenTransitions).startEnterTransition(anyInt(),
- wctCaptor.capture(), any(), any(), anyInt(), anyBoolean());
+ verify(mSplitScreenTransitions).startEnterTransition(anyInt(),
+ mWctCaptor.capture(), any(), any(), anyInt(), anyBoolean());
+
+ int windowingMode = mWctCaptor.getValue().getChanges().get(mBinder).getWindowingMode();
+ assertEquals(windowingMode, WINDOWING_MODE_UNDEFINED);
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_ENABLE_FULL_SCREEN_WINDOW_ON_REMOVING_SPLIT_SCREEN_STAGE_BUGFIX)
+ public void startTasksOnSingleFreeformWindow_ensureWindowingModeClearedAndLaunchFullScreen() {
+ mDisplayAreaInfo.configuration.windowConfiguration.setWindowingMode(
+ WINDOWING_MODE_FREEFORM);
+ when(mRunningTaskInfo.getWindowingMode()).thenReturn(WINDOWING_MODE_FREEFORM);
+
+ mStageCoordinator.startTasks(mTaskId, null, INVALID_TASK_ID, null,
+ SPLIT_POSITION_TOP_OR_LEFT, SNAP_TO_2_50_50, mRemoteTransition,
+ InstanceId.fakeInstanceId(0));
- int windowingMode = wctCaptor.getValue().getChanges().get(binder).getWindowingMode();
+ verify(mSplitScreenTransitions).startFullscreenTransition(mWctCaptor.capture(), any());
+ int windowingMode = mWctCaptor.getValue().getChanges().get(mBinder).getWindowingMode();
assertEquals(windowingMode, WINDOWING_MODE_UNDEFINED);
}
+
+ @Test
+ @DisableFlags(Flags.FLAG_ENABLE_FULL_SCREEN_WINDOW_ON_REMOVING_SPLIT_SCREEN_STAGE_BUGFIX)
+ public void startTasksOnSingleFreeformWindow_flagDisabled_noChangeToWindowingModeInWct() {
+ mDisplayAreaInfo.configuration.windowConfiguration.setWindowingMode(
+ WINDOWING_MODE_FREEFORM);
+ when(mRunningTaskInfo.getWindowingMode()).thenReturn(WINDOWING_MODE_FREEFORM);
+
+ mStageCoordinator.startTasks(mTaskId, null, INVALID_TASK_ID, null,
+ SPLIT_POSITION_TOP_OR_LEFT, SNAP_TO_2_50_50, mRemoteTransition,
+ InstanceId.fakeInstanceId(0));
+
+ verify(mSplitScreenTransitions).startFullscreenTransition(mWctCaptor.capture(), any());
+ assertThat(mWctCaptor.getValue().getChanges()).isEmpty();
+ }
+
@Test
public void testDismiss_freeformDisplay() {
mDisplayAreaInfo.configuration.windowConfiguration.setWindowingMode(