diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java b/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java index eb82c6d597d4e..dc61345708b10 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java @@ -182,6 +182,11 @@ class AppPair implements ShellTaskOrganizer.TaskListener, SplitLayout.LayoutChan @Override public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) { + if (!taskInfo.supportsMultiWindow) { + // Dismiss AppPair if the task no longer supports multi window. + mController.unpair(mRootTaskInfo.taskId); + return; + } if (taskInfo.taskId == getRootTaskId()) { if (mRootTaskInfo.isVisible != taskInfo.isVisible) { mSyncQueue.runInSync(t -> { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenTaskListener.java index cf35656a395be..13596ea5e8860 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenTaskListener.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenTaskListener.java @@ -203,6 +203,22 @@ class LegacySplitScreenTaskListener implements ShellTaskOrganizer.TaskListener { return; } synchronized (this) { + if (!taskInfo.supportsMultiWindow) { + if (mSplitScreenController.isDividerVisible()) { + // Dismiss the split screen if the task no longer supports multi window. + if (taskInfo.taskId == mPrimary.taskId + || taskInfo.parentTaskId == mPrimary.taskId) { + // If the primary is focused, dismiss to primary. + mSplitScreenController + .startDismissSplit(taskInfo.isFocused /* toPrimaryTask */); + } else { + // If the secondary is not focused, dismiss to primary. + mSplitScreenController + .startDismissSplit(!taskInfo.isFocused /* toPrimaryTask */); + } + } + return; + } if (taskInfo.hasParentTask()) { // changed messages are noisy since it reports on every ensureVisibility. This // conflicts with legacy app-transitions which "swaps" the position to a 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 4be9e758bf9b8..eb60dc25ccd26 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 @@ -908,6 +908,13 @@ class StageCoordinator implements SplitLayout.LayoutChangeListener, StageCoordinator.this.onStageRootTaskVanished(this); } + @Override + public void onNoLongerSupportMultiWindow() { + if (mMainStage.isActive()) { + StageCoordinator.this.exitSplitScreen(); + } + } + private void reset() { mHasRootTask = false; mVisible = false; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java index 1da0a2d827663..147a9df7fefe6 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java @@ -61,6 +61,7 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener { void onStatusChanged(boolean visible, boolean hasChildren); void onChildTaskStatusChanged(int taskId, boolean present, boolean visible); void onRootTaskVanished(); + void onNoLongerSupportMultiWindow(); } private final StageListenerCallbacks mCallbacks; private final SyncTransactionQueue mSyncQueue; @@ -113,6 +114,11 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener { @Override @CallSuper public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) { + if (!taskInfo.supportsMultiWindow) { + // Leave split screen if the task no longer supports multi window. + mCallbacks.onNoLongerSupportMultiWindow(); + return; + } if (mRootTaskInfo.taskId == taskInfo.taskId) { mRootTaskInfo = taskInfo; } else if (taskInfo.parentTaskId == mRootTaskInfo.taskId) { diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/apppairs/AppPairTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/apppairs/AppPairTests.java index d21183e10ed90..e73d9aaf190a8 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/apppairs/AppPairTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/apppairs/AppPairTests.java @@ -18,9 +18,12 @@ package com.android.wm.shell.apppairs; import static android.view.Display.DEFAULT_DISPLAY; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; + import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.ActivityManager; @@ -43,7 +46,11 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; -/** Tests for {@link AppPair} */ +/** + * Tests for {@link AppPair} + * Build/Install/Run: + * atest WMShellUnitTests:AppPairTests + */ @SmallTest @RunWith(AndroidJUnit4.class) public class AppPairTests extends ShellTestCase { @@ -63,6 +70,7 @@ public class AppPairTests extends ShellTestCase { mTaskOrganizer, mSyncQueue, mDisplayController); + spyOn(mController); } @After @@ -97,4 +105,19 @@ public class AppPairTests extends ShellTestCase { assertThat(pair.contains(task1.taskId)).isFalse(); assertThat(pair.contains(task2.taskId)).isFalse(); } + + @Test + @UiThreadTest + public void testOnTaskInfoChanged_notSupportsMultiWindow() { + final ActivityManager.RunningTaskInfo task1 = new TestRunningTaskInfoBuilder().build(); + final ActivityManager.RunningTaskInfo task2 = new TestRunningTaskInfoBuilder().build(); + + final AppPair pair = mController.pairInner(task1, task2); + assertThat(pair.contains(task1.taskId)).isTrue(); + assertThat(pair.contains(task2.taskId)).isTrue(); + + task1.supportsMultiWindow = false; + pair.onTaskInfoChanged(task1); + verify(mController).unpair(pair.getRootTaskId()); + } } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java index c66e0730422ce..b3d2be99db147 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java @@ -41,7 +41,11 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; -/** Tests for {@link StageTaskListener} */ +/** + * Tests for {@link StageTaskListener} + * Build/Install/Run: + * atest WMShellUnitTests:StageTaskListenerTests + */ @SmallTest @RunWith(AndroidJUnit4.class) public final class StageTaskListenerTests { @@ -101,4 +105,14 @@ public final class StageTaskListenerTests { mStageTaskListener.onTaskVanished(mRootTask); verify(mCallbacks).onRootTaskVanished(); } + + @Test + public void testTaskInfoChanged_notSupportsMultiWindow() { + final ActivityManager.RunningTaskInfo childTask = + new TestRunningTaskInfoBuilder().setParentTaskId(mRootTask.taskId).build(); + childTask.supportsMultiWindow = false; + + mStageTaskListener.onTaskInfoChanged(childTask); + verify(mCallbacks).onNoLongerSupportMultiWindow(); + } }