Merge "Correct the pair-to-pair transition animation" into udc-dev

This commit is contained in:
Wei Sheng Shih
2023-05-25 01:27:59 +00:00
committed by Android (Google) Code Review
4 changed files with 74 additions and 6 deletions

View File

@@ -192,6 +192,9 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
private final SplitScreenTransitions mSplitTransitions; private final SplitScreenTransitions mSplitTransitions;
private final SplitscreenEventLogger mLogger; private final SplitscreenEventLogger mLogger;
private final ShellExecutor mMainExecutor; 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 Optional<RecentTasksController> mRecentTasks;
private final Rect mTempRect1 = new Rect(); private final Rect mTempRect1 = new Rect();
@@ -658,6 +661,10 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
// Add task launch requests // Add task launch requests
wct.startTask(mainTaskId, mainOptions); wct.startTask(mainTaskId, mainOptions);
// leave recents animation by re-start pausing tasks
if (mPausingTasks.contains(mainTaskId)) {
mPausingTasks.clear();
}
mSplitTransitions.startEnterTransition( mSplitTransitions.startEnterTransition(
TRANSIT_TO_FRONT, wct, remoteTransition, this, null, null, TRANSIT_TO_FRONT, wct, remoteTransition, this, null, null,
TRANSIT_SPLIT_SCREEN_PAIR_OPEN, false); TRANSIT_SPLIT_SCREEN_PAIR_OPEN, false);
@@ -1630,7 +1637,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
} }
private void updateRecentTasksSplitPair() { private void updateRecentTasksSplitPair() {
if (!mShouldUpdateRecents) { // Preventing from single task update while processing recents.
if (!mShouldUpdateRecents || !mPausingTasks.isEmpty()) {
return; return;
} }
mRecentTasks.ifPresent(recentTasks -> { mRecentTasks.ifPresent(recentTasks -> {
@@ -2582,6 +2590,9 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
final TransitionInfo.Change change = info.getChanges().get(iC); final TransitionInfo.Change change = info.getChanges().get(iC);
final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo(); final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
if (taskInfo == null || !taskInfo.hasParentTask()) continue; if (taskInfo == null || !taskInfo.hasParentTask()) continue;
if (mPausingTasks.contains(taskInfo.taskId)) {
continue;
}
final @StageType int stageType = getStageType(getStageOfTask(taskInfo)); final @StageType int stageType = getStageType(getStageOfTask(taskInfo));
if (stageType == STAGE_TYPE_MAIN if (stageType == STAGE_TYPE_MAIN
&& (isOpeningType(change.getMode()) || change.getMode() == TRANSIT_CHANGE)) { && (isOpeningType(change.getMode()) || change.getMode() == TRANSIT_CHANGE)) {
@@ -2654,6 +2665,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mShowDecorImmediately = true; mShowDecorImmediately = true;
mSplitLayout.flingDividerToCenter(); mSplitLayout.flingDividerToCenter();
} }
mPausingTasks.clear();
}); });
finishEnterSplitScreen(finishT); 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. */ /** Call this when starting the open-recents animation while split-screen is active. */
public void onRecentsInSplitAnimationStart(TransitionInfo info) { 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 */); 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. */ /** Call this when the recents animation during split-screen finishes. */
public void onRecentsInSplitAnimationFinish(WindowContainerTransaction finishWct, 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 // Check if the recent transition is finished by returning to the current
// split, so we can restore the divider bar. // split, so we can restore the divider bar.
for (int i = 0; i < finishWct.getHierarchyOps().size(); ++i) { for (int i = 0; i < finishWct.getHierarchyOps().size(); ++i) {
@@ -2840,6 +2873,27 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
logExit(EXIT_REASON_UNKNOWN); 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) { private void addDividerBarToTransition(@NonNull TransitionInfo info, boolean show) {
final SurfaceControl leash = mSplitLayout.getDividerLeash(); final SurfaceControl leash = mSplitLayout.getDividerLeash();
if (leash == null || !leash.isValid()) { if (leash == null || !leash.isValid()) {
@@ -2892,6 +2946,9 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
pw.println(innerPrefix + "SplitLayout"); pw.println(innerPrefix + "SplitLayout");
mSplitLayout.dump(pw, childPrefix); mSplitLayout.dump(pw, childPrefix);
} }
if (!mPausingTasks.isEmpty()) {
pw.println(childPrefix + "mPausingTasks=" + mPausingTasks);
}
} }
/** /**

View File

@@ -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) { void reparentTopTask(WindowContainerTransaction wct) {
wct.reparentTasks(null /* currentParent */, mRootTaskInfo.token, wct.reparentTasks(null /* currentParent */, mRootTaskInfo.token,
CONTROLLED_WINDOWING_MODES, CONTROLLED_ACTIVITY_TYPES, CONTROLLED_WINDOWING_MODES, CONTROLLED_ACTIVITY_TYPES,

View File

@@ -540,9 +540,12 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler,
mixed.mInFlightSubAnimations = 0; mixed.mInFlightSubAnimations = 0;
mActiveTransitions.remove(mixed); mActiveTransitions.remove(mixed);
// If pair-to-pair switching, the post-recents clean-up isn't needed. // 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) { if (mixed.mAnimType != MixedTransition.ANIM_TYPE_PAIR_TO_PAIR) {
wct = wct != null ? wct : new WindowContainerTransaction(); mSplitHandler.onRecentsInSplitAnimationFinish(wct, finishTransaction);
mSplitHandler.onRecentsInSplitAnimationFinish(wct, finishTransaction, info); } else {
// notify pair-to-pair recents animation finish
mSplitHandler.onRecentsPairToPairAnimationFinish(wct);
} }
mSplitHandler.onTransitionAnimationComplete(); mSplitHandler.onTransitionAnimationComplete();
finishCallback.onTransitionFinished(wct, wctCB); finishCallback.onTransitionFinished(wct, wctCB);
@@ -552,6 +555,7 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler,
final boolean handled = mixed.mLeftoversHandler.startAnimation(mixed.mTransition, info, final boolean handled = mixed.mLeftoversHandler.startAnimation(mixed.mTransition, info,
startTransaction, finishTransaction, finishCB); startTransaction, finishTransaction, finishCB);
if (!handled) { if (!handled) {
mSplitHandler.onRecentsInSplitAnimationCanceled();
mActiveTransitions.remove(mixed); mActiveTransitions.remove(mixed);
} }
return handled; return handled;

View File

@@ -283,7 +283,7 @@ public class SplitTransitionTests extends ShellTestCase {
// Make sure it cleans-up if recents doesn't restore // Make sure it cleans-up if recents doesn't restore
WindowContainerTransaction commitWCT = new WindowContainerTransaction(); WindowContainerTransaction commitWCT = new WindowContainerTransaction();
mStageCoordinator.onRecentsInSplitAnimationFinish(commitWCT, mStageCoordinator.onRecentsInSplitAnimationFinish(commitWCT,
mock(SurfaceControl.Transaction.class), mock(TransitionInfo.class)); mock(SurfaceControl.Transaction.class));
assertFalse(mStageCoordinator.isSplitScreenVisible()); assertFalse(mStageCoordinator.isSplitScreenVisible());
} }
@@ -322,7 +322,7 @@ public class SplitTransitionTests extends ShellTestCase {
mMainStage.onTaskAppeared(mMainChild, mock(SurfaceControl.class)); mMainStage.onTaskAppeared(mMainChild, mock(SurfaceControl.class));
mSideStage.onTaskAppeared(mSideChild, mock(SurfaceControl.class)); mSideStage.onTaskAppeared(mSideChild, mock(SurfaceControl.class));
mStageCoordinator.onRecentsInSplitAnimationFinish(restoreWCT, mStageCoordinator.onRecentsInSplitAnimationFinish(restoreWCT,
mock(SurfaceControl.Transaction.class), mock(TransitionInfo.class)); mock(SurfaceControl.Transaction.class));
assertTrue(mStageCoordinator.isSplitScreenVisible()); assertTrue(mStageCoordinator.isSplitScreenVisible());
} }