Loading libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java +2 −2 Original line number Diff line number Diff line Loading @@ -261,9 +261,9 @@ public abstract class PipTransitionController implements Transitions.TransitionH } /** Whether a particular package is same as current pip package. */ public boolean isInPipPackage(String packageName) { public boolean isPackageActiveInPip(String packageName) { final TaskInfo inPipTask = mPipOrganizer.getTaskInfo(); return packageName != null && inPipTask != null return packageName != null && inPipTask != null && mPipOrganizer.isInPip() && packageName.equals(SplitScreenUtils.getPackageName(inPipTask.baseIntent)); } Loading libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +91 −18 Original line number Diff line number Diff line Loading @@ -201,7 +201,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, private final DisplayImeController mDisplayImeController; private final DisplayInsetsController mDisplayInsetsController; private final TransactionPool mTransactionPool; private final SplitScreenTransitions mSplitTransitions; private SplitScreenTransitions mSplitTransitions; private final SplitscreenEventLogger mLogger; private final ShellExecutor mMainExecutor; // Cache live tile tasks while entering recents, evict them from stages in finish transaction Loading Loading @@ -399,6 +399,11 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, return mSplitTransitions; } @VisibleForTesting void setSplitTransitions(SplitScreenTransitions splitScreenTransitions) { mSplitTransitions = splitScreenTransitions; } public boolean isSplitScreenVisible() { return mSideStageListener.mVisible && mMainStageListener.mVisible; } Loading Loading @@ -583,7 +588,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, options = resolveStartStage(STAGE_TYPE_UNDEFINED, position, options, null /* wct */); wct.startTask(taskId, options); // If this should be mixed, send the task to avoid split handle transition directly. if (mMixedHandler != null && mMixedHandler.shouldSplitEnterMixed(taskId, mTaskOrganizer)) { if (mMixedHandler != null && mMixedHandler.isTaskInPip(taskId, mTaskOrganizer)) { mTaskOrganizer.applyTransaction(wct); return; } Loading Loading @@ -622,7 +627,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, wct.sendPendingIntent(intent, fillInIntent, options); // If this should be mixed, just send the intent to avoid split handle transition directly. if (mMixedHandler != null && mMixedHandler.shouldSplitEnterMixed(intent)) { if (mMixedHandler != null && mMixedHandler.isIntentInPip(intent)) { mTaskOrganizer.applyTransaction(wct); return; } Loading Loading @@ -711,16 +716,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, taskId1, taskId2, splitPosition, snapPosition); final WindowContainerTransaction wct = new WindowContainerTransaction(); if (taskId2 == INVALID_TASK_ID) { if (mMainStage.containsTask(taskId1) || mSideStage.containsTask(taskId1)) { prepareExitSplitScreen(STAGE_TYPE_UNDEFINED, wct); } if (mRecentTasks.isPresent()) { mRecentTasks.get().removeSplitPair(taskId1); } options1 = options1 != null ? options1 : new Bundle(); addActivityOptions(options1, null); wct.startTask(taskId1, options1); mSplitTransitions.startFullscreenTransition(wct, remoteTransition); startSingleTask(taskId1, options1, wct, remoteTransition); return; } Loading @@ -741,11 +737,15 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, "startIntentAndTask: intent=%s task1=%d position=%d snapPosition=%d", pendingIntent.getIntent(), taskId, splitPosition, snapPosition); final WindowContainerTransaction wct = new WindowContainerTransaction(); if (taskId == INVALID_TASK_ID) { options1 = options1 != null ? options1 : new Bundle(); addActivityOptions(options1, null); wct.sendPendingIntent(pendingIntent, fillInIntent, options1); mSplitTransitions.startFullscreenTransition(wct, remoteTransition); boolean firstIntentPipped = mMixedHandler.isIntentInPip(pendingIntent); boolean secondTaskPipped = mMixedHandler.isTaskInPip(taskId, mTaskOrganizer); if (taskId == INVALID_TASK_ID || secondTaskPipped) { startSingleIntent(pendingIntent, fillInIntent, options1, wct, remoteTransition); return; } if (firstIntentPipped) { startSingleTask(taskId, options2, wct, remoteTransition); return; } Loading @@ -757,6 +757,24 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, startWithTask(wct, taskId, options2, snapPosition, remoteTransition, instanceId); } /** * @param taskId Starts this task in fullscreen, removing it from existing pairs if it was part * of one. */ private void startSingleTask(int taskId, Bundle options, WindowContainerTransaction wct, RemoteTransition remoteTransition) { if (mMainStage.containsTask(taskId) || mSideStage.containsTask(taskId)) { prepareExitSplitScreen(STAGE_TYPE_UNDEFINED, wct); } if (mRecentTasks.isPresent()) { mRecentTasks.get().removeSplitPair(taskId); } options = options != null ? options : new Bundle(); addActivityOptions(options, null); wct.startTask(taskId, options); mSplitTransitions.startFullscreenTransition(wct, remoteTransition); } /** Starts a shortcut and a task to a split pair in one transition. */ void startShortcutAndTask(ShortcutInfo shortcutInfo, @Nullable Bundle options1, int taskId, @Nullable Bundle options2, @SplitPosition int splitPosition, Loading Loading @@ -844,6 +862,21 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, return; } boolean handledForPipSplitLaunch = handlePippedSplitIntentsLaunch( pendingIntent1, pendingIntent2, options1, options2, shortcutInfo1, shortcutInfo2, wct, fillInIntent1, fillInIntent2, remoteTransition); if (handledForPipSplitLaunch) { return; } if (!mMainStage.isActive()) { // Build a request WCT that will launch both apps such that task 0 is on the main stage // while task 1 is on the side stage. Loading Loading @@ -878,6 +911,46 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, setEnterInstanceId(instanceId); } /** * Checks if either of the apps in the desired split launch is currently in Pip. If so, it will * launch the non-pipped app as a fullscreen app, otherwise no-op. */ private boolean handlePippedSplitIntentsLaunch(PendingIntent pendingIntent1, PendingIntent pendingIntent2, Bundle options1, Bundle options2, ShortcutInfo shortcutInfo1, ShortcutInfo shortcutInfo2, WindowContainerTransaction wct, Intent fillInIntent1, Intent fillInIntent2, RemoteTransition remoteTransition) { // If one of the split apps to start is in Pip, only launch the non-pip app in fullscreen boolean firstIntentPipped = mMixedHandler.isIntentInPip(pendingIntent1); boolean secondIntentPipped = mMixedHandler.isIntentInPip(pendingIntent2); if (firstIntentPipped || secondIntentPipped) { Bundle options = secondIntentPipped ? options1 : options2; options = options == null ? new Bundle() : options; addActivityOptions(options, null); if (shortcutInfo1 != null || shortcutInfo2 != null) { ShortcutInfo infoToLaunch = secondIntentPipped ? shortcutInfo1 : shortcutInfo2; wct.startShortcut(mContext.getPackageName(), infoToLaunch, options); mSplitTransitions.startFullscreenTransition(wct, remoteTransition); } else { PendingIntent intentToLaunch = secondIntentPipped ? pendingIntent1 : pendingIntent2; Intent fillInIntentToLaunch = secondIntentPipped ? fillInIntent1 : fillInIntent2; startSingleIntent(intentToLaunch, fillInIntentToLaunch, options, wct, remoteTransition); } return true; } return false; } /** @param pendingIntent Starts this intent in fullscreen */ private void startSingleIntent(PendingIntent pendingIntent, Intent fillInIntent, Bundle options, WindowContainerTransaction wct, RemoteTransition remoteTransition) { Bundle optionsToLaunch = options != null ? options : new Bundle(); addActivityOptions(optionsToLaunch, null); wct.sendPendingIntent(pendingIntent, fillInIntent, optionsToLaunch); mSplitTransitions.startFullscreenTransition(wct, remoteTransition); } /** Starts a pair of tasks using legacy transition. */ void startTasksWithLegacyTransition(int taskId1, @Nullable Bundle options1, int taskId2, @Nullable Bundle options2, @SplitPosition int splitPosition, Loading libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java +5 −4 Original line number Diff line number Diff line Loading @@ -563,22 +563,23 @@ public class DefaultMixedHandler implements MixedTransitionHandler, /** Use to when split use intent to enter, check if this enter transition should be mixed or * not.*/ public boolean shouldSplitEnterMixed(PendingIntent intent) { public boolean isIntentInPip(PendingIntent intent) { // Check if this intent package is same as pip one or not, if true we want let the pip // task enter split. if (mPipHandler != null) { return mPipHandler.isInPipPackage(SplitScreenUtils.getPackageName(intent.getIntent())); return mPipHandler .isPackageActiveInPip(SplitScreenUtils.getPackageName(intent.getIntent())); } return false; } /** Use to when split use taskId to enter, check if this enter transition should be mixed or * not.*/ public boolean shouldSplitEnterMixed(int taskId, ShellTaskOrganizer shellTaskOrganizer) { public boolean isTaskInPip(int taskId, ShellTaskOrganizer shellTaskOrganizer) { // Check if this intent package is same as pip one or not, if true we want let the pip // task enter split. if (mPipHandler != null) { return mPipHandler.isInPipPackage( return mPipHandler.isPackageActiveInPip( SplitScreenUtils.getPackageName(taskId, shellTaskOrganizer)); } return false; Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java +96 −0 Original line number Diff line number Diff line Loading @@ -40,10 +40,12 @@ import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.ActivityManager; import android.app.PendingIntent; import android.content.res.Configuration; import android.graphics.Rect; import android.os.Bundle; Loading @@ -51,6 +53,7 @@ import android.os.Handler; import android.os.Looper; import android.view.SurfaceControl; import android.view.SurfaceSession; import android.window.RemoteTransition; import android.window.WindowContainerToken; import android.window.WindowContainerTransaction; Loading @@ -74,6 +77,7 @@ import com.android.wm.shell.common.split.SplitLayout; import com.android.wm.shell.splitscreen.SplitScreen.SplitScreenListener; import com.android.wm.shell.sysui.ShellController; import com.android.wm.shell.sysui.ShellInit; import com.android.wm.shell.transition.DefaultMixedHandler; import com.android.wm.shell.transition.HomeTransitionObserver; import com.android.wm.shell.transition.Transitions; Loading Loading @@ -111,6 +115,8 @@ public class StageCoordinatorTests extends ShellTestCase { private TransactionPool mTransactionPool; @Mock private LaunchAdjacentController mLaunchAdjacentController; @Mock private DefaultMixedHandler mDefaultMixedHandler; private final Rect mBounds1 = new Rect(10, 20, 30, 40); private final Rect mBounds2 = new Rect(5, 10, 15, 20); Loading Loading @@ -370,6 +376,96 @@ 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( pendingIntent, null /*fillInIntent*/, null /*option1*/, taskId, null /*option2*/, 0 /*splitPosition*/, 1 /*snapPosition*/, remoteTransition /*remoteTransition*/, null /*instanceId*/); verify(splitScreenTransitions, times(1)) .startFullscreenTransition(any(), any()); // Test launching first intent fullscreen when(mDefaultMixedHandler.isIntentInPip(pendingIntent)).thenReturn(false); when(mDefaultMixedHandler.isTaskInPip(taskId, mTaskOrganizer)).thenReturn(true); mStageCoordinator.startIntentAndTask( pendingIntent, null /*fillInIntent*/, null /*option1*/, taskId, null /*option2*/, 0 /*splitPosition*/, 1 /*snapPosition*/, remoteTransition /*remoteTransition*/, null /*instanceId*/); verify(splitScreenTransitions, 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( pendingIntent, null /*fillInIntent*/, null /*shortcutInfo1*/, new Bundle(), pendingIntent2, null /*fillInIntent2*/, null /*shortcutInfo1*/, new Bundle(), 0 /*splitPosition*/, 1 /*snapPosition*/, remoteTransition /*remoteTransition*/, null /*instanceId*/); verify(splitScreenTransitions, times(1)) .startFullscreenTransition(any(), any()); // Test launching first intent fullscreen when(mDefaultMixedHandler.isIntentInPip(pendingIntent)).thenReturn(false); when(mDefaultMixedHandler.isIntentInPip(pendingIntent2)).thenReturn(true); mStageCoordinator.startIntents( pendingIntent, null /*fillInIntent*/, null /*shortcutInfo1*/, new Bundle(), pendingIntent2, null /*fillInIntent2*/, null /*shortcutInfo1*/, new Bundle(), 0 /*splitPosition*/, 1 /*snapPosition*/, remoteTransition /*remoteTransition*/, null /*instanceId*/); verify(splitScreenTransitions, times(2)) .startFullscreenTransition(any(), any()); } private Transitions createTestTransitions() { ShellInit shellInit = new ShellInit(mMainExecutor); final Transitions t = new Transitions(mContext, shellInit, mock(ShellController.class), Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java +2 −2 Original line number Diff line number Diff line Loading @@ -261,9 +261,9 @@ public abstract class PipTransitionController implements Transitions.TransitionH } /** Whether a particular package is same as current pip package. */ public boolean isInPipPackage(String packageName) { public boolean isPackageActiveInPip(String packageName) { final TaskInfo inPipTask = mPipOrganizer.getTaskInfo(); return packageName != null && inPipTask != null return packageName != null && inPipTask != null && mPipOrganizer.isInPip() && packageName.equals(SplitScreenUtils.getPackageName(inPipTask.baseIntent)); } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +91 −18 Original line number Diff line number Diff line Loading @@ -201,7 +201,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, private final DisplayImeController mDisplayImeController; private final DisplayInsetsController mDisplayInsetsController; private final TransactionPool mTransactionPool; private final SplitScreenTransitions mSplitTransitions; private SplitScreenTransitions mSplitTransitions; private final SplitscreenEventLogger mLogger; private final ShellExecutor mMainExecutor; // Cache live tile tasks while entering recents, evict them from stages in finish transaction Loading Loading @@ -399,6 +399,11 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, return mSplitTransitions; } @VisibleForTesting void setSplitTransitions(SplitScreenTransitions splitScreenTransitions) { mSplitTransitions = splitScreenTransitions; } public boolean isSplitScreenVisible() { return mSideStageListener.mVisible && mMainStageListener.mVisible; } Loading Loading @@ -583,7 +588,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, options = resolveStartStage(STAGE_TYPE_UNDEFINED, position, options, null /* wct */); wct.startTask(taskId, options); // If this should be mixed, send the task to avoid split handle transition directly. if (mMixedHandler != null && mMixedHandler.shouldSplitEnterMixed(taskId, mTaskOrganizer)) { if (mMixedHandler != null && mMixedHandler.isTaskInPip(taskId, mTaskOrganizer)) { mTaskOrganizer.applyTransaction(wct); return; } Loading Loading @@ -622,7 +627,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, wct.sendPendingIntent(intent, fillInIntent, options); // If this should be mixed, just send the intent to avoid split handle transition directly. if (mMixedHandler != null && mMixedHandler.shouldSplitEnterMixed(intent)) { if (mMixedHandler != null && mMixedHandler.isIntentInPip(intent)) { mTaskOrganizer.applyTransaction(wct); return; } Loading Loading @@ -711,16 +716,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, taskId1, taskId2, splitPosition, snapPosition); final WindowContainerTransaction wct = new WindowContainerTransaction(); if (taskId2 == INVALID_TASK_ID) { if (mMainStage.containsTask(taskId1) || mSideStage.containsTask(taskId1)) { prepareExitSplitScreen(STAGE_TYPE_UNDEFINED, wct); } if (mRecentTasks.isPresent()) { mRecentTasks.get().removeSplitPair(taskId1); } options1 = options1 != null ? options1 : new Bundle(); addActivityOptions(options1, null); wct.startTask(taskId1, options1); mSplitTransitions.startFullscreenTransition(wct, remoteTransition); startSingleTask(taskId1, options1, wct, remoteTransition); return; } Loading @@ -741,11 +737,15 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, "startIntentAndTask: intent=%s task1=%d position=%d snapPosition=%d", pendingIntent.getIntent(), taskId, splitPosition, snapPosition); final WindowContainerTransaction wct = new WindowContainerTransaction(); if (taskId == INVALID_TASK_ID) { options1 = options1 != null ? options1 : new Bundle(); addActivityOptions(options1, null); wct.sendPendingIntent(pendingIntent, fillInIntent, options1); mSplitTransitions.startFullscreenTransition(wct, remoteTransition); boolean firstIntentPipped = mMixedHandler.isIntentInPip(pendingIntent); boolean secondTaskPipped = mMixedHandler.isTaskInPip(taskId, mTaskOrganizer); if (taskId == INVALID_TASK_ID || secondTaskPipped) { startSingleIntent(pendingIntent, fillInIntent, options1, wct, remoteTransition); return; } if (firstIntentPipped) { startSingleTask(taskId, options2, wct, remoteTransition); return; } Loading @@ -757,6 +757,24 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, startWithTask(wct, taskId, options2, snapPosition, remoteTransition, instanceId); } /** * @param taskId Starts this task in fullscreen, removing it from existing pairs if it was part * of one. */ private void startSingleTask(int taskId, Bundle options, WindowContainerTransaction wct, RemoteTransition remoteTransition) { if (mMainStage.containsTask(taskId) || mSideStage.containsTask(taskId)) { prepareExitSplitScreen(STAGE_TYPE_UNDEFINED, wct); } if (mRecentTasks.isPresent()) { mRecentTasks.get().removeSplitPair(taskId); } options = options != null ? options : new Bundle(); addActivityOptions(options, null); wct.startTask(taskId, options); mSplitTransitions.startFullscreenTransition(wct, remoteTransition); } /** Starts a shortcut and a task to a split pair in one transition. */ void startShortcutAndTask(ShortcutInfo shortcutInfo, @Nullable Bundle options1, int taskId, @Nullable Bundle options2, @SplitPosition int splitPosition, Loading Loading @@ -844,6 +862,21 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, return; } boolean handledForPipSplitLaunch = handlePippedSplitIntentsLaunch( pendingIntent1, pendingIntent2, options1, options2, shortcutInfo1, shortcutInfo2, wct, fillInIntent1, fillInIntent2, remoteTransition); if (handledForPipSplitLaunch) { return; } if (!mMainStage.isActive()) { // Build a request WCT that will launch both apps such that task 0 is on the main stage // while task 1 is on the side stage. Loading Loading @@ -878,6 +911,46 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, setEnterInstanceId(instanceId); } /** * Checks if either of the apps in the desired split launch is currently in Pip. If so, it will * launch the non-pipped app as a fullscreen app, otherwise no-op. */ private boolean handlePippedSplitIntentsLaunch(PendingIntent pendingIntent1, PendingIntent pendingIntent2, Bundle options1, Bundle options2, ShortcutInfo shortcutInfo1, ShortcutInfo shortcutInfo2, WindowContainerTransaction wct, Intent fillInIntent1, Intent fillInIntent2, RemoteTransition remoteTransition) { // If one of the split apps to start is in Pip, only launch the non-pip app in fullscreen boolean firstIntentPipped = mMixedHandler.isIntentInPip(pendingIntent1); boolean secondIntentPipped = mMixedHandler.isIntentInPip(pendingIntent2); if (firstIntentPipped || secondIntentPipped) { Bundle options = secondIntentPipped ? options1 : options2; options = options == null ? new Bundle() : options; addActivityOptions(options, null); if (shortcutInfo1 != null || shortcutInfo2 != null) { ShortcutInfo infoToLaunch = secondIntentPipped ? shortcutInfo1 : shortcutInfo2; wct.startShortcut(mContext.getPackageName(), infoToLaunch, options); mSplitTransitions.startFullscreenTransition(wct, remoteTransition); } else { PendingIntent intentToLaunch = secondIntentPipped ? pendingIntent1 : pendingIntent2; Intent fillInIntentToLaunch = secondIntentPipped ? fillInIntent1 : fillInIntent2; startSingleIntent(intentToLaunch, fillInIntentToLaunch, options, wct, remoteTransition); } return true; } return false; } /** @param pendingIntent Starts this intent in fullscreen */ private void startSingleIntent(PendingIntent pendingIntent, Intent fillInIntent, Bundle options, WindowContainerTransaction wct, RemoteTransition remoteTransition) { Bundle optionsToLaunch = options != null ? options : new Bundle(); addActivityOptions(optionsToLaunch, null); wct.sendPendingIntent(pendingIntent, fillInIntent, optionsToLaunch); mSplitTransitions.startFullscreenTransition(wct, remoteTransition); } /** Starts a pair of tasks using legacy transition. */ void startTasksWithLegacyTransition(int taskId1, @Nullable Bundle options1, int taskId2, @Nullable Bundle options2, @SplitPosition int splitPosition, Loading
libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java +5 −4 Original line number Diff line number Diff line Loading @@ -563,22 +563,23 @@ public class DefaultMixedHandler implements MixedTransitionHandler, /** Use to when split use intent to enter, check if this enter transition should be mixed or * not.*/ public boolean shouldSplitEnterMixed(PendingIntent intent) { public boolean isIntentInPip(PendingIntent intent) { // Check if this intent package is same as pip one or not, if true we want let the pip // task enter split. if (mPipHandler != null) { return mPipHandler.isInPipPackage(SplitScreenUtils.getPackageName(intent.getIntent())); return mPipHandler .isPackageActiveInPip(SplitScreenUtils.getPackageName(intent.getIntent())); } return false; } /** Use to when split use taskId to enter, check if this enter transition should be mixed or * not.*/ public boolean shouldSplitEnterMixed(int taskId, ShellTaskOrganizer shellTaskOrganizer) { public boolean isTaskInPip(int taskId, ShellTaskOrganizer shellTaskOrganizer) { // Check if this intent package is same as pip one or not, if true we want let the pip // task enter split. if (mPipHandler != null) { return mPipHandler.isInPipPackage( return mPipHandler.isPackageActiveInPip( SplitScreenUtils.getPackageName(taskId, shellTaskOrganizer)); } return false; Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java +96 −0 Original line number Diff line number Diff line Loading @@ -40,10 +40,12 @@ import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.ActivityManager; import android.app.PendingIntent; import android.content.res.Configuration; import android.graphics.Rect; import android.os.Bundle; Loading @@ -51,6 +53,7 @@ import android.os.Handler; import android.os.Looper; import android.view.SurfaceControl; import android.view.SurfaceSession; import android.window.RemoteTransition; import android.window.WindowContainerToken; import android.window.WindowContainerTransaction; Loading @@ -74,6 +77,7 @@ import com.android.wm.shell.common.split.SplitLayout; import com.android.wm.shell.splitscreen.SplitScreen.SplitScreenListener; import com.android.wm.shell.sysui.ShellController; import com.android.wm.shell.sysui.ShellInit; import com.android.wm.shell.transition.DefaultMixedHandler; import com.android.wm.shell.transition.HomeTransitionObserver; import com.android.wm.shell.transition.Transitions; Loading Loading @@ -111,6 +115,8 @@ public class StageCoordinatorTests extends ShellTestCase { private TransactionPool mTransactionPool; @Mock private LaunchAdjacentController mLaunchAdjacentController; @Mock private DefaultMixedHandler mDefaultMixedHandler; private final Rect mBounds1 = new Rect(10, 20, 30, 40); private final Rect mBounds2 = new Rect(5, 10, 15, 20); Loading Loading @@ -370,6 +376,96 @@ 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( pendingIntent, null /*fillInIntent*/, null /*option1*/, taskId, null /*option2*/, 0 /*splitPosition*/, 1 /*snapPosition*/, remoteTransition /*remoteTransition*/, null /*instanceId*/); verify(splitScreenTransitions, times(1)) .startFullscreenTransition(any(), any()); // Test launching first intent fullscreen when(mDefaultMixedHandler.isIntentInPip(pendingIntent)).thenReturn(false); when(mDefaultMixedHandler.isTaskInPip(taskId, mTaskOrganizer)).thenReturn(true); mStageCoordinator.startIntentAndTask( pendingIntent, null /*fillInIntent*/, null /*option1*/, taskId, null /*option2*/, 0 /*splitPosition*/, 1 /*snapPosition*/, remoteTransition /*remoteTransition*/, null /*instanceId*/); verify(splitScreenTransitions, 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( pendingIntent, null /*fillInIntent*/, null /*shortcutInfo1*/, new Bundle(), pendingIntent2, null /*fillInIntent2*/, null /*shortcutInfo1*/, new Bundle(), 0 /*splitPosition*/, 1 /*snapPosition*/, remoteTransition /*remoteTransition*/, null /*instanceId*/); verify(splitScreenTransitions, times(1)) .startFullscreenTransition(any(), any()); // Test launching first intent fullscreen when(mDefaultMixedHandler.isIntentInPip(pendingIntent)).thenReturn(false); when(mDefaultMixedHandler.isIntentInPip(pendingIntent2)).thenReturn(true); mStageCoordinator.startIntents( pendingIntent, null /*fillInIntent*/, null /*shortcutInfo1*/, new Bundle(), pendingIntent2, null /*fillInIntent2*/, null /*shortcutInfo1*/, new Bundle(), 0 /*splitPosition*/, 1 /*snapPosition*/, remoteTransition /*remoteTransition*/, null /*instanceId*/); verify(splitScreenTransitions, times(2)) .startFullscreenTransition(any(), any()); } private Transitions createTestTransitions() { ShellInit shellInit = new ShellInit(mMainExecutor); final Transitions t = new Transitions(mContext, shellInit, mock(ShellController.class), Loading