diff options
4 files changed, 74 insertions, 6 deletions
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 e0ffffffa727..256d48c5618c 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 @@ -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(); @@ -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); @@ -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 -> { @@ -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)) { @@ -2654,6 +2665,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, mShowDecorImmediately = true; mSplitLayout.flingDividerToCenter(); } + mPausingTasks.clear(); }); finishEnterSplitScreen(finishT); @@ -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) { @@ -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()) { @@ -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); + } } /** 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 da7d18641a97..92ff5fed4584 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 @@ -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, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java index 863b5ab73a7d..64571e067a83 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java @@ -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. + wct = wct != null ? wct : new WindowContainerTransaction(); if (mixed.mAnimType != MixedTransition.ANIM_TYPE_PAIR_TO_PAIR) { - wct = wct != null ? wct : new WindowContainerTransaction(); - mSplitHandler.onRecentsInSplitAnimationFinish(wct, finishTransaction, info); + mSplitHandler.onRecentsInSplitAnimationFinish(wct, finishTransaction); + } else { + // notify pair-to-pair recents animation finish + mSplitHandler.onRecentsPairToPairAnimationFinish(wct); } mSplitHandler.onTransitionAnimationComplete(); finishCallback.onTransitionFinished(wct, wctCB); @@ -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; diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java index 60c0e5535568..5f705d743601 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java @@ -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()); } @@ -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()); } |