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 ec71fbee9a294..3b75bfb933c9b 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 @@ -215,10 +215,12 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, options = mStageCoordinator.resolveStartStage(stage, position, options, null /* wct */); try { + final WindowContainerTransaction evictWct = new WindowContainerTransaction(); + mStageCoordinator.prepareEvictChildTasks(position, evictWct); final int result = ActivityTaskManager.getService().startActivityFromRecents(taskId, options); if (result == START_SUCCESS || result == START_TASK_TO_FRONT) { - mStageCoordinator.evictOccludedChildren(position); + mSyncQueue.queue(evictWct); } } catch (RemoteException e) { Slog.e(TAG, "Failed to launch task", e); @@ -229,13 +231,15 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, @SplitScreen.StageType int stage, @SplitPosition int position, @Nullable Bundle options, UserHandle user) { options = mStageCoordinator.resolveStartStage(stage, position, options, null /* wct */); + final WindowContainerTransaction evictWct = new WindowContainerTransaction(); + mStageCoordinator.prepareEvictChildTasks(position, evictWct); try { LauncherApps launcherApps = mContext.getSystemService(LauncherApps.class); launcherApps.startShortcut(packageName, shortcutId, null /* sourceBounds */, options, user); - mStageCoordinator.evictOccludedChildren(position); + mSyncQueue.queue(evictWct); } catch (ActivityNotFoundException e) { Slog.e(TAG, "Failed to launch shortcut", e); } @@ -255,6 +259,9 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, private void startIntentLegacy(PendingIntent intent, Intent fillInIntent, @SplitScreen.StageType int stage, @SplitPosition int position, @Nullable Bundle options) { + final WindowContainerTransaction evictWct = new WindowContainerTransaction(); + mStageCoordinator.prepareEvictChildTasks(position, evictWct); + LegacyTransitions.ILegacyTransition transition = new LegacyTransitions.ILegacyTransition() { @Override public void onAnimationStart(int transit, RemoteAnimationTarget[] apps, @@ -280,12 +287,11 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, } } - // Launching a new app into a specific split evicts tasks previously in the same - // split. - mStageCoordinator.evictOccludedChildren(position); + mSyncQueue.queue(evictWct); } }; - WindowContainerTransaction wct = new WindowContainerTransaction(); + + final WindowContainerTransaction wct = new WindowContainerTransaction(); options = mStageCoordinator.resolveStartStage(stage, position, options, wct); wct.sendPendingIntent(intent, fillInIntent, options); mSyncQueue.queue(transition, WindowManager.TRANSIT_OPEN, wct); 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 0cff18e2ba85f..72d9880d0aa1a 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 @@ -394,10 +394,16 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, TRANSIT_SPLIT_SCREEN_OPEN_TO_SIDE, wct, remoteTransition, this); } - void evictOccludedChildren(@SplitPosition int position) { - final WindowContainerTransaction wct = new WindowContainerTransaction(); - (position == mSideStagePosition ? mSideStage : mMainStage).evictOccludedChildren(wct); - mTaskOrganizer.applyTransaction(wct); + /** + * Collects all the current child tasks of a specific split and prepares transaction to evict + * them to display. + */ + void prepareEvictChildTasks(@SplitPosition int position, WindowContainerTransaction wct) { + if (position == mSideStagePosition) { + mSideStage.evictAllChildren(wct); + } else { + mMainStage.evictAllChildren(wct); + } } Bundle resolveStartStage(@SplitScreen.StageType int stage, 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 071badf2bc23a..6f1a09dc88e62 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 @@ -248,12 +248,11 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener { wct.reorder(mChildrenTaskInfo.get(taskId).token, onTop /* onTop */); } - void evictOccludedChildren(WindowContainerTransaction wct) { + /** Collects all the current child tasks and prepares transaction to evict them to display. */ + void evictAllChildren(WindowContainerTransaction wct) { for (int i = mChildrenTaskInfo.size() - 1; i >= 0; i--) { final ActivityManager.RunningTaskInfo taskInfo = mChildrenTaskInfo.valueAt(i); - if (!taskInfo.isVisible) { - wct.reparent(taskInfo.token, null /* parent */, false /* onTop */); - } + wct.reparent(taskInfo.token, null /* parent */, false /* onTop */); } } 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 a5746a49da2b9..3ed72e2c079e3 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 @@ -21,6 +21,8 @@ import static android.view.Display.DEFAULT_DISPLAY; import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.junit.Assume.assumeFalse; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.clearInvocations; @@ -31,6 +33,7 @@ import android.app.ActivityManager; import android.os.SystemProperties; import android.view.SurfaceControl; import android.view.SurfaceSession; +import android.window.WindowContainerTransaction; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; @@ -50,7 +53,7 @@ import org.mockito.MockitoAnnotations; /** * Tests for {@link StageTaskListener} * Build/Install/Run: - * atest WMShellUnitTests:StageTaskListenerTests + * atest WMShellUnitTests:StageTaskListenerTests */ @SmallTest @RunWith(AndroidJUnit4.class) @@ -58,11 +61,16 @@ public final class StageTaskListenerTests { private static final boolean ENABLE_SHELL_TRANSITIONS = SystemProperties.getBoolean("persist.debug.shell_transit", false); - @Mock private ShellTaskOrganizer mTaskOrganizer; - @Mock private StageTaskListener.StageListenerCallbacks mCallbacks; - @Mock private SyncTransactionQueue mSyncQueue; - @Mock private StageTaskUnfoldController mStageTaskUnfoldController; - @Captor private ArgumentCaptor mRunnableCaptor; + @Mock + private ShellTaskOrganizer mTaskOrganizer; + @Mock + private StageTaskListener.StageListenerCallbacks mCallbacks; + @Mock + private SyncTransactionQueue mSyncQueue; + @Mock + private StageTaskUnfoldController mStageTaskUnfoldController; + @Captor + private ArgumentCaptor mRunnableCaptor; private SurfaceSession mSurfaceSession = new SurfaceSession(); private SurfaceControl mSurfaceControl; private ActivityManager.RunningTaskInfo mRootTask; @@ -167,4 +175,18 @@ public final class StageTaskListenerTests { mStageTaskListener.onTaskInfoChanged(childTask); verify(mCallbacks).onNoLongerSupportMultiWindow(); } + + @Test + public void testEvictAllChildren() { + final WindowContainerTransaction wct = new WindowContainerTransaction(); + mStageTaskListener.evictAllChildren(wct); + assertTrue(wct.isEmpty()); + + final ActivityManager.RunningTaskInfo childTask = + new TestRunningTaskInfoBuilder().setParentTaskId(mRootTask.taskId).build(); + mStageTaskListener.onTaskAppeared(childTask, mSurfaceControl); + + mStageTaskListener.evictAllChildren(wct); + assertFalse(wct.isEmpty()); + } }