Loading libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +59 −2 Original line number Diff line number Diff line Loading @@ -192,6 +192,9 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, private final SplitScreenTransitions mSplitTransitions; private final SplitscreenEventLogger mLogger; private final ShellExecutor mMainExecutor; // Cache live tile tasks while entering recents, evict them from stages in finish transaction // if user is opening another task(s). private final ArrayList<Integer> mPausingTasks = new ArrayList<>(); private final Optional<RecentTasksController> mRecentTasks; private final Rect mTempRect1 = new Rect(); Loading Loading @@ -658,6 +661,10 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, // Add task launch requests wct.startTask(mainTaskId, mainOptions); // leave recents animation by re-start pausing tasks if (mPausingTasks.contains(mainTaskId)) { mPausingTasks.clear(); } mSplitTransitions.startEnterTransition( TRANSIT_TO_FRONT, wct, remoteTransition, this, null, null, TRANSIT_SPLIT_SCREEN_PAIR_OPEN, false); Loading Loading @@ -1630,7 +1637,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, } private void updateRecentTasksSplitPair() { if (!mShouldUpdateRecents) { // Preventing from single task update while processing recents. if (!mShouldUpdateRecents || !mPausingTasks.isEmpty()) { return; } mRecentTasks.ifPresent(recentTasks -> { Loading Loading @@ -2582,6 +2590,9 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, final TransitionInfo.Change change = info.getChanges().get(iC); final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo(); if (taskInfo == null || !taskInfo.hasParentTask()) continue; if (mPausingTasks.contains(taskInfo.taskId)) { continue; } final @StageType int stageType = getStageType(getStageOfTask(taskInfo)); if (stageType == STAGE_TYPE_MAIN && (isOpeningType(change.getMode()) || change.getMode() == TRANSIT_CHANGE)) { Loading Loading @@ -2654,6 +2665,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, mShowDecorImmediately = true; mSplitLayout.flingDividerToCenter(); } mPausingTasks.clear(); }); finishEnterSplitScreen(finishT); Loading Loading @@ -2811,12 +2823,33 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, /** Call this when starting the open-recents animation while split-screen is active. */ public void onRecentsInSplitAnimationStart(TransitionInfo info) { if (isSplitScreenVisible()) { // Cache tasks on live tile. for (int i = 0; i < info.getChanges().size(); ++i) { final TransitionInfo.Change change = info.getChanges().get(i); if (TransitionUtil.isClosingType(change.getMode()) && change.getTaskInfo() != null) { final int taskId = change.getTaskInfo().taskId; if (mMainStage.getTopVisibleChildTaskId() == taskId || mSideStage.getTopVisibleChildTaskId() == taskId) { mPausingTasks.add(taskId); } } } } addDividerBarToTransition(info, false /* show */); } /** Call this when the recents animation canceled during split-screen. */ public void onRecentsInSplitAnimationCanceled() { mPausingTasks.clear(); } /** Call this when the recents animation during split-screen finishes. */ public void onRecentsInSplitAnimationFinish(WindowContainerTransaction finishWct, SurfaceControl.Transaction finishT, TransitionInfo info) { SurfaceControl.Transaction finishT) { mPausingTasks.clear(); // Check if the recent transition is finished by returning to the current // split, so we can restore the divider bar. for (int i = 0; i < finishWct.getHierarchyOps().size(); ++i) { Loading @@ -2840,6 +2873,27 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, logExit(EXIT_REASON_UNKNOWN); } /** Call this when the recents animation finishes by doing pair-to-pair switch. */ public void onRecentsPairToPairAnimationFinish(WindowContainerTransaction finishWct) { // Pair-to-pair switch happened so here should evict the live tile from its stage. // Otherwise, the task will remain in stage, and occluding the new task when next time // user entering recents. for (int i = mPausingTasks.size() - 1; i >= 0; --i) { final int taskId = mPausingTasks.get(i); if (mMainStage.containsTask(taskId)) { mMainStage.evictChildren(finishWct, taskId); } else if (mSideStage.containsTask(taskId)) { mSideStage.evictChildren(finishWct, taskId); } } // If pending enter hasn't consumed, the mix handler will invoke start pending // animation within following transition. if (mSplitTransitions.mPendingEnter == null) { mPausingTasks.clear(); updateRecentTasksSplitPair(); } } private void addDividerBarToTransition(@NonNull TransitionInfo info, boolean show) { final SurfaceControl leash = mSplitLayout.getDividerLeash(); if (leash == null || !leash.isValid()) { Loading Loading @@ -2892,6 +2946,9 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, pw.println(innerPrefix + "SplitLayout"); mSplitLayout.dump(pw, childPrefix); } if (!mPausingTasks.isEmpty()) { pw.println(childPrefix + "mPausingTasks=" + mPausingTasks); } } /** Loading libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java +7 −0 Original line number Diff line number Diff line Loading @@ -377,6 +377,13 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener { } } void evictChildren(WindowContainerTransaction wct, int taskId) { final ActivityManager.RunningTaskInfo taskInfo = mChildrenTaskInfo.get(taskId); if (taskInfo != null) { wct.reparent(taskInfo.token, null /* parent */, false /* onTop */); } } void reparentTopTask(WindowContainerTransaction wct) { wct.reparentTasks(null /* currentParent */, mRootTaskInfo.token, CONTROLLED_WINDOWING_MODES, CONTROLLED_ACTIVITY_TYPES, Loading libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java +6 −2 Original line number Diff line number Diff line Loading @@ -540,9 +540,12 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler, mixed.mInFlightSubAnimations = 0; mActiveTransitions.remove(mixed); // If pair-to-pair switching, the post-recents clean-up isn't needed. if (mixed.mAnimType != MixedTransition.ANIM_TYPE_PAIR_TO_PAIR) { wct = wct != null ? wct : new WindowContainerTransaction(); mSplitHandler.onRecentsInSplitAnimationFinish(wct, finishTransaction, info); if (mixed.mAnimType != MixedTransition.ANIM_TYPE_PAIR_TO_PAIR) { mSplitHandler.onRecentsInSplitAnimationFinish(wct, finishTransaction); } else { // notify pair-to-pair recents animation finish mSplitHandler.onRecentsPairToPairAnimationFinish(wct); } mSplitHandler.onTransitionAnimationComplete(); finishCallback.onTransitionFinished(wct, wctCB); Loading @@ -552,6 +555,7 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler, final boolean handled = mixed.mLeftoversHandler.startAnimation(mixed.mTransition, info, startTransaction, finishTransaction, finishCB); if (!handled) { mSplitHandler.onRecentsInSplitAnimationCanceled(); mActiveTransitions.remove(mixed); } return handled; Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java +2 −2 Original line number Diff line number Diff line Loading @@ -283,7 +283,7 @@ public class SplitTransitionTests extends ShellTestCase { // Make sure it cleans-up if recents doesn't restore WindowContainerTransaction commitWCT = new WindowContainerTransaction(); mStageCoordinator.onRecentsInSplitAnimationFinish(commitWCT, mock(SurfaceControl.Transaction.class), mock(TransitionInfo.class)); mock(SurfaceControl.Transaction.class)); assertFalse(mStageCoordinator.isSplitScreenVisible()); } Loading Loading @@ -322,7 +322,7 @@ public class SplitTransitionTests extends ShellTestCase { mMainStage.onTaskAppeared(mMainChild, mock(SurfaceControl.class)); mSideStage.onTaskAppeared(mSideChild, mock(SurfaceControl.class)); mStageCoordinator.onRecentsInSplitAnimationFinish(restoreWCT, mock(SurfaceControl.Transaction.class), mock(TransitionInfo.class)); mock(SurfaceControl.Transaction.class)); assertTrue(mStageCoordinator.isSplitScreenVisible()); } Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +59 −2 Original line number Diff line number Diff line Loading @@ -192,6 +192,9 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, private final SplitScreenTransitions mSplitTransitions; private final SplitscreenEventLogger mLogger; private final ShellExecutor mMainExecutor; // Cache live tile tasks while entering recents, evict them from stages in finish transaction // if user is opening another task(s). private final ArrayList<Integer> mPausingTasks = new ArrayList<>(); private final Optional<RecentTasksController> mRecentTasks; private final Rect mTempRect1 = new Rect(); Loading Loading @@ -658,6 +661,10 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, // Add task launch requests wct.startTask(mainTaskId, mainOptions); // leave recents animation by re-start pausing tasks if (mPausingTasks.contains(mainTaskId)) { mPausingTasks.clear(); } mSplitTransitions.startEnterTransition( TRANSIT_TO_FRONT, wct, remoteTransition, this, null, null, TRANSIT_SPLIT_SCREEN_PAIR_OPEN, false); Loading Loading @@ -1630,7 +1637,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, } private void updateRecentTasksSplitPair() { if (!mShouldUpdateRecents) { // Preventing from single task update while processing recents. if (!mShouldUpdateRecents || !mPausingTasks.isEmpty()) { return; } mRecentTasks.ifPresent(recentTasks -> { Loading Loading @@ -2582,6 +2590,9 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, final TransitionInfo.Change change = info.getChanges().get(iC); final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo(); if (taskInfo == null || !taskInfo.hasParentTask()) continue; if (mPausingTasks.contains(taskInfo.taskId)) { continue; } final @StageType int stageType = getStageType(getStageOfTask(taskInfo)); if (stageType == STAGE_TYPE_MAIN && (isOpeningType(change.getMode()) || change.getMode() == TRANSIT_CHANGE)) { Loading Loading @@ -2654,6 +2665,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, mShowDecorImmediately = true; mSplitLayout.flingDividerToCenter(); } mPausingTasks.clear(); }); finishEnterSplitScreen(finishT); Loading Loading @@ -2811,12 +2823,33 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, /** Call this when starting the open-recents animation while split-screen is active. */ public void onRecentsInSplitAnimationStart(TransitionInfo info) { if (isSplitScreenVisible()) { // Cache tasks on live tile. for (int i = 0; i < info.getChanges().size(); ++i) { final TransitionInfo.Change change = info.getChanges().get(i); if (TransitionUtil.isClosingType(change.getMode()) && change.getTaskInfo() != null) { final int taskId = change.getTaskInfo().taskId; if (mMainStage.getTopVisibleChildTaskId() == taskId || mSideStage.getTopVisibleChildTaskId() == taskId) { mPausingTasks.add(taskId); } } } } addDividerBarToTransition(info, false /* show */); } /** Call this when the recents animation canceled during split-screen. */ public void onRecentsInSplitAnimationCanceled() { mPausingTasks.clear(); } /** Call this when the recents animation during split-screen finishes. */ public void onRecentsInSplitAnimationFinish(WindowContainerTransaction finishWct, SurfaceControl.Transaction finishT, TransitionInfo info) { SurfaceControl.Transaction finishT) { mPausingTasks.clear(); // Check if the recent transition is finished by returning to the current // split, so we can restore the divider bar. for (int i = 0; i < finishWct.getHierarchyOps().size(); ++i) { Loading @@ -2840,6 +2873,27 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, logExit(EXIT_REASON_UNKNOWN); } /** Call this when the recents animation finishes by doing pair-to-pair switch. */ public void onRecentsPairToPairAnimationFinish(WindowContainerTransaction finishWct) { // Pair-to-pair switch happened so here should evict the live tile from its stage. // Otherwise, the task will remain in stage, and occluding the new task when next time // user entering recents. for (int i = mPausingTasks.size() - 1; i >= 0; --i) { final int taskId = mPausingTasks.get(i); if (mMainStage.containsTask(taskId)) { mMainStage.evictChildren(finishWct, taskId); } else if (mSideStage.containsTask(taskId)) { mSideStage.evictChildren(finishWct, taskId); } } // If pending enter hasn't consumed, the mix handler will invoke start pending // animation within following transition. if (mSplitTransitions.mPendingEnter == null) { mPausingTasks.clear(); updateRecentTasksSplitPair(); } } private void addDividerBarToTransition(@NonNull TransitionInfo info, boolean show) { final SurfaceControl leash = mSplitLayout.getDividerLeash(); if (leash == null || !leash.isValid()) { Loading Loading @@ -2892,6 +2946,9 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, pw.println(innerPrefix + "SplitLayout"); mSplitLayout.dump(pw, childPrefix); } if (!mPausingTasks.isEmpty()) { pw.println(childPrefix + "mPausingTasks=" + mPausingTasks); } } /** Loading
libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java +7 −0 Original line number Diff line number Diff line Loading @@ -377,6 +377,13 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener { } } void evictChildren(WindowContainerTransaction wct, int taskId) { final ActivityManager.RunningTaskInfo taskInfo = mChildrenTaskInfo.get(taskId); if (taskInfo != null) { wct.reparent(taskInfo.token, null /* parent */, false /* onTop */); } } void reparentTopTask(WindowContainerTransaction wct) { wct.reparentTasks(null /* currentParent */, mRootTaskInfo.token, CONTROLLED_WINDOWING_MODES, CONTROLLED_ACTIVITY_TYPES, Loading
libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java +6 −2 Original line number Diff line number Diff line Loading @@ -540,9 +540,12 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler, mixed.mInFlightSubAnimations = 0; mActiveTransitions.remove(mixed); // If pair-to-pair switching, the post-recents clean-up isn't needed. if (mixed.mAnimType != MixedTransition.ANIM_TYPE_PAIR_TO_PAIR) { wct = wct != null ? wct : new WindowContainerTransaction(); mSplitHandler.onRecentsInSplitAnimationFinish(wct, finishTransaction, info); if (mixed.mAnimType != MixedTransition.ANIM_TYPE_PAIR_TO_PAIR) { mSplitHandler.onRecentsInSplitAnimationFinish(wct, finishTransaction); } else { // notify pair-to-pair recents animation finish mSplitHandler.onRecentsPairToPairAnimationFinish(wct); } mSplitHandler.onTransitionAnimationComplete(); finishCallback.onTransitionFinished(wct, wctCB); Loading @@ -552,6 +555,7 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler, final boolean handled = mixed.mLeftoversHandler.startAnimation(mixed.mTransition, info, startTransaction, finishTransaction, finishCB); if (!handled) { mSplitHandler.onRecentsInSplitAnimationCanceled(); mActiveTransitions.remove(mixed); } return handled; Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java +2 −2 Original line number Diff line number Diff line Loading @@ -283,7 +283,7 @@ public class SplitTransitionTests extends ShellTestCase { // Make sure it cleans-up if recents doesn't restore WindowContainerTransaction commitWCT = new WindowContainerTransaction(); mStageCoordinator.onRecentsInSplitAnimationFinish(commitWCT, mock(SurfaceControl.Transaction.class), mock(TransitionInfo.class)); mock(SurfaceControl.Transaction.class)); assertFalse(mStageCoordinator.isSplitScreenVisible()); } Loading Loading @@ -322,7 +322,7 @@ public class SplitTransitionTests extends ShellTestCase { mMainStage.onTaskAppeared(mMainChild, mock(SurfaceControl.class)); mSideStage.onTaskAppeared(mSideChild, mock(SurfaceControl.class)); mStageCoordinator.onRecentsInSplitAnimationFinish(restoreWCT, mock(SurfaceControl.Transaction.class), mock(TransitionInfo.class)); mock(SurfaceControl.Transaction.class)); assertTrue(mStageCoordinator.isSplitScreenVisible()); } Loading