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

Commit 6019b99d authored by Vania Desmonda's avatar Vania Desmonda
Browse files

Fix split screen exit bug on a freeform task.

Clear the windowing mode of the task that is partially shown on the side
stage so that when the split screen is cancelled, the task is launched
in full screen.

Test: atest StageCoordinatorTests
Flag: com.android.window.flags.enable_full_screen_window_on_removing_split_screen_stage_bugfix
Fixes: 372791604
Change-Id: Ie7c261e274fb0c29595e00e209997610b7ffec77
parent 7f4179c4
Loading
Loading
Loading
Loading
+6 −0
Original line number Original line Diff line number Diff line
@@ -34,6 +34,7 @@ import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static android.window.TransitionInfo.FLAG_IS_DISPLAY;
import static android.window.TransitionInfo.FLAG_IS_DISPLAY;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REORDER;
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.window.flags.Flags.enableNonDefaultDisplaySplit;
import static com.android.wm.shell.Flags.enableFlexibleSplit;
import static com.android.wm.shell.Flags.enableFlexibleSplit;
import static com.android.wm.shell.Flags.enableFlexibleTwoAppSplit;
import static com.android.wm.shell.Flags.enableFlexibleTwoAppSplit;
@@ -908,6 +909,11 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        }
        }
        options = options != null ? options : new Bundle();
        options = options != null ? options : new Bundle();
        addActivityOptions(options, null);
        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);
        wct.startTask(taskId, options);
        mSplitTransitions.startFullscreenTransition(wct, remoteTransition);
        mSplitTransitions.startFullscreenTransition(wct, remoteTransition);
    }
    }
+97 −67
Original line number Original line Diff line number Diff line
@@ -22,6 +22,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.view.Display.DEFAULT_DISPLAY;
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_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_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
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.Handler;
import android.os.IBinder;
import android.os.IBinder;
import android.os.Looper;
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.view.SurfaceControl;
import android.window.DisplayAreaInfo;
import android.window.DisplayAreaInfo;
import android.window.RemoteTransition;
import android.window.RemoteTransition;
@@ -71,6 +75,8 @@ import androidx.test.annotation.UiThreadTest;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
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.MockToken;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.ShellTaskOrganizer;
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 com.android.wm.shell.transition.Transitions;


import org.junit.Before;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentCaptor;
@@ -111,6 +118,9 @@ import java.util.function.Consumer;
@SmallTest
@SmallTest
@RunWith(AndroidJUnit4.class)
@RunWith(AndroidJUnit4.class)
public class StageCoordinatorTests extends ShellTestCase {
public class StageCoordinatorTests extends ShellTestCase {
    @Rule
    public final SetFlagsRule setFlagsRule = new SetFlagsRule();

    @Mock
    @Mock
    private ShellTaskOrganizer mTaskOrganizer;
    private ShellTaskOrganizer mTaskOrganizer;
    @Mock
    @Mock
@@ -141,12 +151,15 @@ public class StageCoordinatorTests extends ShellTestCase {
    private final Rect mBounds1 = new Rect(10, 20, 30, 40);
    private final Rect mBounds1 = new Rect(10, 20, 30, 40);
    private final Rect mBounds2 = new Rect(5, 10, 15, 20);
    private final Rect mBounds2 = new Rect(5, 10, 15, 20);
    private final Rect mRootBounds = new Rect(0, 0, 45, 60);
    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 ActivityManager.RunningTaskInfo mRootTask;
    private StageCoordinator mStageCoordinator;
    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 TestShellExecutor mMainExecutor = new TestShellExecutor();
    private final ShellExecutor mAnimExecutor = new TestShellExecutor();
    private final ShellExecutor mAnimExecutor = new TestShellExecutor();
    private final Handler mMainHandler = new Handler(Looper.getMainLooper());
    private final Handler mMainHandler = new Handler(Looper.getMainLooper());
@@ -154,19 +167,35 @@ public class StageCoordinatorTests extends ShellTestCase {
            DEFAULT_DISPLAY, 0);
            DEFAULT_DISPLAY, 0);
    private final ActivityManager.RunningTaskInfo mMainChildTaskInfo =
    private final ActivityManager.RunningTaskInfo mMainChildTaskInfo =
            new TestRunningTaskInfoBuilder().setVisible(true).build();
            new TestRunningTaskInfoBuilder().setVisible(true).build();
    private final ArgumentCaptor<WindowContainerTransaction> mWctCaptor =
            ArgumentCaptor.forClass(WindowContainerTransaction.class);
    private final WindowContainerTransaction mWct = spy(new WindowContainerTransaction());


    @Before
    @Before
    @UiThreadTest
    @UiThreadTest
    public void setup() {
    public void setup() {
        MockitoAnnotations.initMocks(this);
        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,
        mStageCoordinator = spy(new StageCoordinator(mContext, DEFAULT_DISPLAY, mSyncQueue,
                mTaskOrganizer, mMainStage, mSideStage, mDisplayController, mDisplayImeController,
                mTaskOrganizer, mMainStage, mSideStage, mDisplayController, mDisplayImeController,
                mDisplayInsetsController, mSplitLayout, mTransitions, mTransactionPool,
                mDisplayInsetsController, mSplitLayout, transitions, mTransactionPool,
                mMainExecutor, mMainHandler, Optional.empty(), mLaunchAdjacentController,
                mMainExecutor, mMainHandler, Optional.empty(), mLaunchAdjacentController,
                Optional.empty(), mSplitState, Optional.empty(), mRootTDAOrganizer));
                Optional.empty(), mSplitState, Optional.empty(), mRootTDAOrganizer));

        mSplitScreenTransitions = spy(mStageCoordinator.getSplitTransitions());
        mDividerLeash = new SurfaceControl.Builder().setName("fakeDivider").build();
        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(mRootTDAOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY)).thenReturn(mDisplayAreaInfo);


        when(mSplitLayout.getTopLeftBounds()).thenReturn(mBounds1);
        when(mSplitLayout.getTopLeftBounds()).thenReturn(mBounds1);
@@ -174,11 +203,11 @@ public class StageCoordinatorTests extends ShellTestCase {
        when(mSplitLayout.getRootBounds()).thenReturn(mRootBounds);
        when(mSplitLayout.getRootBounds()).thenReturn(mRootBounds);
        when(mSplitLayout.isLeftRightSplit()).thenReturn(false);
        when(mSplitLayout.isLeftRightSplit()).thenReturn(false);
        when(mSplitLayout.applyTaskChanges(any(), any(), any())).thenReturn(true);
        when(mSplitLayout.applyTaskChanges(any(), any(), any())).thenReturn(true);
        when(mSplitLayout.getDividerLeash()).thenReturn(mDividerLeash);
        when(mSplitLayout.getDividerLeash()).thenReturn(dividerLeash);


        mRootTask = new TestRunningTaskInfoBuilder().build();
        mRootTask = new TestRunningTaskInfoBuilder().build();
        mRootLeash = new SurfaceControl.Builder().setName("test").build();
        SurfaceControl rootLeash = new SurfaceControl.Builder().setName("test").build();
        mStageCoordinator.onTaskAppeared(mRootTask, mRootLeash);
        mStageCoordinator.onTaskAppeared(mRootTask, rootLeash);


        mSideStage.mRootTaskInfo = new TestRunningTaskInfoBuilder().build();
        mSideStage.mRootTaskInfo = new TestRunningTaskInfoBuilder().build();
        mMainStage.mRootTaskInfo = new TestRunningTaskInfoBuilder().build();
        mMainStage.mRootTaskInfo = new TestRunningTaskInfoBuilder().build();
@@ -196,14 +225,12 @@ public class StageCoordinatorTests extends ShellTestCase {
    public void testMoveToStage_splitActiveBackground() {
    public void testMoveToStage_splitActiveBackground() {
        when(mStageCoordinator.isSplitActive()).thenReturn(true);
        when(mStageCoordinator.isSplitActive()).thenReturn(true);


        final ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder().build();
        mStageCoordinator.moveToStage(mRootTask, SPLIT_POSITION_BOTTOM_OR_RIGHT, mWct);
        final WindowContainerTransaction wct = spy(new WindowContainerTransaction());


        mStageCoordinator.moveToStage(task, SPLIT_POSITION_BOTTOM_OR_RIGHT, wct);
        // TODO(b/349828130) Address this once we remove index_undefined called
        // 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));
                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_BOTTOM_OR_RIGHT, mStageCoordinator.getSideStagePosition());
        assertEquals(SPLIT_POSITION_TOP_OR_LEFT, mStageCoordinator.getMainStagePosition());
        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.
        // Assume current side stage is top or left.
        mStageCoordinator.setSideStagePosition(SPLIT_POSITION_TOP_OR_LEFT, null);
        mStageCoordinator.setSideStagePosition(SPLIT_POSITION_TOP_OR_LEFT, null);


        final ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder().build();
        mStageCoordinator.moveToStage(mRootTask, SPLIT_POSITION_BOTTOM_OR_RIGHT, mWct);
        final WindowContainerTransaction wct = new WindowContainerTransaction();


        mStageCoordinator.moveToStage(task, SPLIT_POSITION_BOTTOM_OR_RIGHT, wct);
        // TODO(b/349828130) Address this once we remove index_undefined called
        // 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));
                eq(SPLIT_POSITION_BOTTOM_OR_RIGHT), eq(false), eq(SPLIT_INDEX_UNDEFINED));
        assertEquals(SPLIT_POSITION_BOTTOM_OR_RIGHT, mStageCoordinator.getMainStagePosition());
        assertEquals(SPLIT_POSITION_BOTTOM_OR_RIGHT, mStageCoordinator.getMainStagePosition());
        assertEquals(SPLIT_POSITION_TOP_OR_LEFT, mStageCoordinator.getSideStagePosition());
        assertEquals(SPLIT_POSITION_TOP_OR_LEFT, mStageCoordinator.getSideStagePosition());
    }
    }


    @Test
    @Test
    public void testMoveToStage_splitInctive() {
    public void testMoveToStage_splitInactive() {
        final ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder().build();
        mStageCoordinator.moveToStage(mRootTask, SPLIT_POSITION_BOTTOM_OR_RIGHT, mWct);
        final WindowContainerTransaction wct = new WindowContainerTransaction();


        mStageCoordinator.moveToStage(task, SPLIT_POSITION_BOTTOM_OR_RIGHT, wct);
        // TODO(b/349828130) Address this once we remove index_undefined called
        // 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));
                eq(SPLIT_POSITION_BOTTOM_OR_RIGHT), eq(false), eq(SPLIT_INDEX_UNDEFINED));
        assertEquals(SPLIT_POSITION_BOTTOM_OR_RIGHT, mStageCoordinator.getSideStagePosition());
        assertEquals(SPLIT_POSITION_BOTTOM_OR_RIGHT, mStageCoordinator.getSideStagePosition());
    }
    }
@@ -248,25 +271,23 @@ public class StageCoordinatorTests extends ShellTestCase {
    @Test
    @Test
    public void testLayoutChanged_topLeftSplitPosition_updatesUnfoldStageBounds() {
    public void testLayoutChanged_topLeftSplitPosition_updatesUnfoldStageBounds() {
        mStageCoordinator.setSideStagePosition(SPLIT_POSITION_TOP_OR_LEFT, null);
        mStageCoordinator.setSideStagePosition(SPLIT_POSITION_TOP_OR_LEFT, null);
        final SplitScreenListener listener = mock(SplitScreenListener.class);
        mStageCoordinator.registerSplitScreenListener(mSplitScreenListener);
        mStageCoordinator.registerSplitScreenListener(listener);
        clearInvocations(mSplitScreenListener);
        clearInvocations(listener);


        mStageCoordinator.onLayoutSizeChanged(mSplitLayout);
        mStageCoordinator.onLayoutSizeChanged(mSplitLayout);


        verify(listener).onSplitBoundsChanged(mRootBounds, mBounds2, mBounds1);
        verify(mSplitScreenListener).onSplitBoundsChanged(mRootBounds, mBounds2, mBounds1);
    }
    }


    @Test
    @Test
    public void testLayoutChanged_bottomRightSplitPosition_updatesUnfoldStageBounds() {
    public void testLayoutChanged_bottomRightSplitPosition_updatesUnfoldStageBounds() {
        mStageCoordinator.setSideStagePosition(SPLIT_POSITION_BOTTOM_OR_RIGHT, null);
        mStageCoordinator.setSideStagePosition(SPLIT_POSITION_BOTTOM_OR_RIGHT, null);
        final SplitScreenListener listener = mock(SplitScreenListener.class);
        mStageCoordinator.registerSplitScreenListener(mSplitScreenListener);
        mStageCoordinator.registerSplitScreenListener(listener);
        clearInvocations(mSplitScreenListener);
        clearInvocations(listener);


        mStageCoordinator.onLayoutSizeChanged(mSplitLayout);
        mStageCoordinator.onLayoutSizeChanged(mSplitLayout);


        verify(listener).onSplitBoundsChanged(mRootBounds, mBounds1, mBounds2);
        verify(mSplitScreenListener).onSplitBoundsChanged(mRootBounds, mBounds1, mBounds2);
    }
    }


    @Test
    @Test
@@ -367,13 +388,8 @@ public class StageCoordinatorTests extends ShellTestCase {
    @Test
    @Test
    public void testSplitIntentAndTaskWithPippedApp_launchFullscreen() {
    public void testSplitIntentAndTaskWithPippedApp_launchFullscreen() {
        int taskId = 9;
        int taskId = 9;
        SplitScreenTransitions splitScreenTransitions =
                spy(mStageCoordinator.getSplitTransitions());
        mStageCoordinator.setSplitTransitions(splitScreenTransitions);
        mStageCoordinator.setMixedHandler(mDefaultMixedHandler);
        mStageCoordinator.setMixedHandler(mDefaultMixedHandler);
        PendingIntent pendingIntent = mock(PendingIntent.class);
        PendingIntent pendingIntent = mock(PendingIntent.class);
        RemoteTransition remoteTransition = mock(RemoteTransition.class);
        when(remoteTransition.getDebugName()).thenReturn("");
        // Test launching second task full screen
        // Test launching second task full screen
        when(mDefaultMixedHandler.isIntentInPip(pendingIntent)).thenReturn(true);
        when(mDefaultMixedHandler.isIntentInPip(pendingIntent)).thenReturn(true);
        mStageCoordinator.startIntentAndTask(
        mStageCoordinator.startIntentAndTask(
@@ -384,9 +400,9 @@ public class StageCoordinatorTests extends ShellTestCase {
                null /*option2*/,
                null /*option2*/,
                0 /*splitPosition*/,
                0 /*splitPosition*/,
                1 /*snapPosition*/,
                1 /*snapPosition*/,
                remoteTransition /*remoteTransition*/,
                mRemoteTransition /*remoteTransition*/,
                null /*instanceId*/);
                null /*instanceId*/);
        verify(splitScreenTransitions, times(1))
        verify(mSplitScreenTransitions, times(1))
                .startFullscreenTransition(any(), any());
                .startFullscreenTransition(any(), any());


        // Test launching first intent fullscreen
        // Test launching first intent fullscreen
@@ -400,22 +416,17 @@ public class StageCoordinatorTests extends ShellTestCase {
                null /*option2*/,
                null /*option2*/,
                0 /*splitPosition*/,
                0 /*splitPosition*/,
                1 /*snapPosition*/,
                1 /*snapPosition*/,
                remoteTransition /*remoteTransition*/,
                mRemoteTransition /*remoteTransition*/,
                null /*instanceId*/);
                null /*instanceId*/);
        verify(splitScreenTransitions, times(2))
        verify(mSplitScreenTransitions, times(2))
                .startFullscreenTransition(any(), any());
                .startFullscreenTransition(any(), any());
    }
    }


    @Test
    @Test
    public void testSplitIntentsWithPippedApp_launchFullscreen() {
    public void testSplitIntentsWithPippedApp_launchFullscreen() {
        SplitScreenTransitions splitScreenTransitions =
                spy(mStageCoordinator.getSplitTransitions());
        mStageCoordinator.setSplitTransitions(splitScreenTransitions);
        mStageCoordinator.setMixedHandler(mDefaultMixedHandler);
        mStageCoordinator.setMixedHandler(mDefaultMixedHandler);
        PendingIntent pendingIntent = mock(PendingIntent.class);
        PendingIntent pendingIntent = mock(PendingIntent.class);
        PendingIntent pendingIntent2 = mock(PendingIntent.class);
        PendingIntent pendingIntent2 = mock(PendingIntent.class);
        RemoteTransition remoteTransition = mock(RemoteTransition.class);
        when(remoteTransition.getDebugName()).thenReturn("");
        // Test launching second task full screen
        // Test launching second task full screen
        when(mDefaultMixedHandler.isIntentInPip(pendingIntent)).thenReturn(true);
        when(mDefaultMixedHandler.isIntentInPip(pendingIntent)).thenReturn(true);
        mStageCoordinator.startIntents(
        mStageCoordinator.startIntents(
@@ -429,9 +440,9 @@ public class StageCoordinatorTests extends ShellTestCase {
                new Bundle(),
                new Bundle(),
                0 /*splitPosition*/,
                0 /*splitPosition*/,
                1 /*snapPosition*/,
                1 /*snapPosition*/,
                remoteTransition /*remoteTransition*/,
                mRemoteTransition /*remoteTransition*/,
                null /*instanceId*/);
                null /*instanceId*/);
        verify(splitScreenTransitions, times(1))
        verify(mSplitScreenTransitions, times(1))
                .startFullscreenTransition(any(), any());
                .startFullscreenTransition(any(), any());


        // Test launching first intent fullscreen
        // Test launching first intent fullscreen
@@ -448,35 +459,54 @@ public class StageCoordinatorTests extends ShellTestCase {
                new Bundle(),
                new Bundle(),
                0 /*splitPosition*/,
                0 /*splitPosition*/,
                1 /*snapPosition*/,
                1 /*snapPosition*/,
                remoteTransition /*remoteTransition*/,
                mRemoteTransition /*remoteTransition*/,
                null /*instanceId*/);
                null /*instanceId*/);
        verify(splitScreenTransitions, times(2))
        verify(mSplitScreenTransitions, times(2))
                .startFullscreenTransition(any(), any());
                .startFullscreenTransition(any(), any());
    }
    }



    @Test
    @Test
    public void startTask_ensureWindowingModeCleared() {
    public void startTask_ensureWindowingModeCleared() {
        SplitScreenTransitions splitScreenTransitions =
        mStageCoordinator.startTask(mTaskId, SPLIT_POSITION_TOP_OR_LEFT, null /*options*/,
                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*/,
                null, SPLIT_INDEX_UNDEFINED);
                null, SPLIT_INDEX_UNDEFINED);
        verify(splitScreenTransitions).startEnterTransition(anyInt(),
        verify(mSplitScreenTransitions).startEnterTransition(anyInt(),
                wctCaptor.capture(), any(), any(), anyInt(), anyBoolean());
                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);
        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
    @Test
    public void testDismiss_freeformDisplay() {
    public void testDismiss_freeformDisplay() {
        mDisplayAreaInfo.configuration.windowConfiguration.setWindowingMode(
        mDisplayAreaInfo.configuration.windowConfiguration.setWindowingMode(