Loading libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java +12 −6 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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); } Loading @@ -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, Loading @@ -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); Loading libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +10 −4 Original line number Diff line number Diff line Loading @@ -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, Loading libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java +3 −4 Original line number Diff line number Diff line Loading @@ -248,14 +248,13 @@ 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 */); } } } void setVisibility(boolean visible, WindowContainerTransaction wct) { wct.reorder(mRootTaskInfo.token, visible /* onTop */); Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java +28 −6 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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<SyncTransactionQueue.TransactionRunnable> mRunnableCaptor; @Mock private ShellTaskOrganizer mTaskOrganizer; @Mock private StageTaskListener.StageListenerCallbacks mCallbacks; @Mock private SyncTransactionQueue mSyncQueue; @Mock private StageTaskUnfoldController mStageTaskUnfoldController; @Captor private ArgumentCaptor<SyncTransactionQueue.TransactionRunnable> mRunnableCaptor; private SurfaceSession mSurfaceSession = new SurfaceSession(); private SurfaceControl mSurfaceControl; private ActivityManager.RunningTaskInfo mRootTask; Loading Loading @@ -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()); } } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java +12 −6 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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); } Loading @@ -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, Loading @@ -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); Loading
libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +10 −4 Original line number Diff line number Diff line Loading @@ -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, Loading
libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java +3 −4 Original line number Diff line number Diff line Loading @@ -248,14 +248,13 @@ 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 */); } } } void setVisibility(boolean visible, WindowContainerTransaction wct) { wct.reorder(mRootTaskInfo.token, visible /* onTop */); Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java +28 −6 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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<SyncTransactionQueue.TransactionRunnable> mRunnableCaptor; @Mock private ShellTaskOrganizer mTaskOrganizer; @Mock private StageTaskListener.StageListenerCallbacks mCallbacks; @Mock private SyncTransactionQueue mSyncQueue; @Mock private StageTaskUnfoldController mStageTaskUnfoldController; @Captor private ArgumentCaptor<SyncTransactionQueue.TransactionRunnable> mRunnableCaptor; private SurfaceSession mSurfaceSession = new SurfaceSession(); private SurfaceControl mSurfaceControl; private ActivityManager.RunningTaskInfo mRootTask; Loading Loading @@ -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()); } }