summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java38
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java74
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java72
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java61
4 files changed, 90 insertions, 155 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java
index 5f1d30f09066..e1c089550c2d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java
@@ -67,6 +67,7 @@ class SplitScreenTransitions {
DismissTransition mPendingDismiss = null;
TransitSession mPendingEnter = null;
+ TransitSession mPendingRecent = null;
TransitSession mPendingResize = null;
private IBinder mAnimatingTransition = null;
@@ -256,6 +257,10 @@ class SplitScreenTransitions {
return mPendingEnter != null && mPendingEnter.mTransition == transition;
}
+ boolean isPendingRecent(IBinder transition) {
+ return mPendingRecent != null && mPendingRecent.mTransition == transition;
+ }
+
boolean isPendingDismiss(IBinder transition) {
return mPendingDismiss != null && mPendingDismiss.mTransition == transition;
}
@@ -268,6 +273,8 @@ class SplitScreenTransitions {
private TransitSession getPendingTransition(IBinder transition) {
if (isPendingEnter(transition)) {
return mPendingEnter;
+ } else if (isPendingRecent(transition)) {
+ return mPendingRecent;
} else if (isPendingDismiss(transition)) {
return mPendingDismiss;
} else if (isPendingResize(transition)) {
@@ -351,10 +358,32 @@ class SplitScreenTransitions {
+ " deduced Resize split screen");
}
+ void setRecentTransition(@NonNull IBinder transition,
+ @Nullable RemoteTransition remoteTransition,
+ @Nullable TransitionFinishedCallback finishCallback) {
+ mPendingRecent = new TransitSession(transition, null /* consumedCb */, finishCallback);
+
+ if (remoteTransition != null) {
+ // Wrapping it for ease-of-use (OneShot handles all the binder linking/death stuff)
+ mPendingRemoteHandler = new OneShotRemoteHandler(
+ mTransitions.getMainExecutor(), remoteTransition);
+ mPendingRemoteHandler.setTransition(transition);
+ }
+
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " splitTransition "
+ + " deduced Enter recent panel");
+ }
+
void mergeAnimation(IBinder transition, TransitionInfo info, SurfaceControl.Transaction t,
IBinder mergeTarget, Transitions.TransitionFinishCallback finishCallback) {
if (mergeTarget != mAnimatingTransition) return;
+ if (isPendingEnter(transition) && isPendingRecent(mergeTarget)) {
+ // Since there's an entering transition merged, recent transition no longer
+ // need to handle entering split screen after the transition finished.
+ mPendingRecent.setFinishedCallback(null);
+ }
+
if (mActiveRemoteHandler != null) {
mActiveRemoteHandler.mergeAnimation(transition, info, t, mergeTarget, finishCallback);
} else {
@@ -391,6 +420,10 @@ class SplitScreenTransitions {
} else if (isPendingDismiss(transition)) {
mPendingDismiss.onConsumed(aborted);
mPendingDismiss = null;
+ } else if (isPendingRecent(transition)) {
+ mPendingRecent.onConsumed(aborted);
+ mPendingRecent = null;
+ mPendingRemoteHandler = null;
} else if (isPendingResize(transition)) {
mPendingResize.onConsumed(aborted);
mPendingResize = null;
@@ -404,6 +437,9 @@ class SplitScreenTransitions {
if (isPendingEnter(mAnimatingTransition)) {
mPendingEnter.onFinished(wct, mFinishTransaction);
mPendingEnter = null;
+ } else if (isPendingRecent(mAnimatingTransition)) {
+ mPendingRecent.onFinished(wct, mFinishTransaction);
+ mPendingRecent = null;
} else if (isPendingDismiss(mAnimatingTransition)) {
mPendingDismiss.onFinished(wct, mFinishTransaction);
mPendingDismiss = null;
@@ -513,7 +549,7 @@ class SplitScreenTransitions {
}
/** Calls when the transition finished. */
- public interface TransitionFinishedCallback {
+ interface TransitionFinishedCallback {
void onFinished(WindowContainerTransaction wct, SurfaceControl.Transaction t);
}
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 9d1a7ea14900..a5546e554422 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
@@ -259,6 +259,37 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
}
};
+ private final SplitScreenTransitions.TransitionFinishedCallback
+ mRecentTransitionFinishedCallback =
+ new SplitScreenTransitions.TransitionFinishedCallback() {
+ @Override
+ public void onFinished(WindowContainerTransaction finishWct,
+ SurfaceControl.Transaction finishT) {
+ // 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) {
+ final WindowContainerTransaction.HierarchyOp op =
+ finishWct.getHierarchyOps().get(i);
+ final IBinder container = op.getContainer();
+ if (op.getType() == HIERARCHY_OP_TYPE_REORDER && op.getToTop()
+ && (mMainStage.containsContainer(container)
+ || mSideStage.containsContainer(container))) {
+ updateSurfaceBounds(mSplitLayout, finishT,
+ false /* applyResizingOffset */);
+ setDividerVisibility(true, finishT);
+ return;
+ }
+ }
+
+ // Dismiss the split screen if it's not returning to split.
+ prepareExitSplitScreen(STAGE_TYPE_UNDEFINED, finishWct);
+ setSplitsVisible(false);
+ setDividerVisibility(false, finishT);
+ logExit(EXIT_REASON_UNKNOWN);
+ }
+ };
+
protected StageCoordinator(Context context, int displayId, SyncTransactionQueue syncQueue,
ShellTaskOrganizer taskOrganizer, DisplayController displayController,
DisplayImeController displayImeController,
@@ -357,11 +388,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
return mMainStage.isActive();
}
- /** Checks if `transition` is a pending enter-split transition. */
- public boolean isPendingEnter(IBinder transition) {
- return mSplitTransitions.isPendingEnter(transition);
- }
-
@StageType
int getStageOfTask(int taskId) {
if (mMainStage.containsTask(taskId)) {
@@ -2240,8 +2266,9 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
final int activityType = triggerTask.getActivityType();
if (activityType == ACTIVITY_TYPE_HOME
|| activityType == ACTIVITY_TYPE_RECENTS) {
- // starting recents, so don't handle this.
- return null;
+ // Enter overview panel, so start recent transition.
+ mSplitTransitions.setRecentTransition(transition, request.getRemoteTransition(),
+ mRecentTransitionFinishedCallback);
}
}
} else {
@@ -2370,6 +2397,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
if (mSplitTransitions.isPendingEnter(transition)) {
shouldAnimate = startPendingEnterAnimation(
transition, info, startTransaction, finishTransaction);
+ } else if (mSplitTransitions.isPendingRecent(transition)) {
+ shouldAnimate = startPendingRecentAnimation(transition, info, startTransaction);
} else if (mSplitTransitions.isPendingDismiss(transition)) {
shouldAnimate = startPendingDismissAnimation(
mSplitTransitions.mPendingDismiss, info, startTransaction, finishTransaction);
@@ -2624,35 +2653,10 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
return true;
}
- /** Call this when starting the open-recents animation while split-screen is active. */
- public void onRecentsInSplitAnimationStart(@NonNull SurfaceControl.Transaction t) {
+ private boolean startPendingRecentAnimation(@NonNull IBinder transition,
+ @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction t) {
setDividerVisibility(false, t);
- }
-
- /** Call this when the recents animation during split-screen finishes. */
- public void onRecentsInSplitAnimationFinish(WindowContainerTransaction finishWct,
- SurfaceControl.Transaction finishT) {
- // 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) {
- final WindowContainerTransaction.HierarchyOp op =
- finishWct.getHierarchyOps().get(i);
- final IBinder container = op.getContainer();
- if (op.getType() == HIERARCHY_OP_TYPE_REORDER && op.getToTop()
- && (mMainStage.containsContainer(container)
- || mSideStage.containsContainer(container))) {
- updateSurfaceBounds(mSplitLayout, finishT,
- false /* applyResizingOffset */);
- setDividerVisibility(true, finishT);
- return;
- }
- }
-
- // Dismiss the split screen if it's not returning to split.
- prepareExitSplitScreen(STAGE_TYPE_UNDEFINED, finishWct);
- setSplitsVisible(false);
- setDividerVisibility(false, finishT);
- logExit(EXIT_REASON_UNKNOWN);
+ return true;
}
private void addDividerBarToTransition(@NonNull TransitionInfo info,
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 095b8da7cfa7..75112b62c1c6 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
@@ -18,7 +18,6 @@ package com.android.wm.shell.transition;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
@@ -26,7 +25,6 @@ import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
import static com.android.wm.shell.common.split.SplitScreenConstants.FLAG_IS_DIVIDER_BAR;
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_CHILD_TASK_ENTER_PIP;
-import static com.android.wm.shell.util.TransitionUtil.isOpeningType;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -70,20 +68,14 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler {
/** Pip was entered while handling an intent with its own remoteTransition. */
static final int TYPE_OPTIONS_REMOTE_AND_PIP_CHANGE = 3;
- /** Recents transition while split-screen active. */
- static final int TYPE_RECENTS_DURING_SPLIT = 4;
-
/** The default animation for this mixed transition. */
static final int ANIM_TYPE_DEFAULT = 0;
/** For ENTER_PIP_FROM_SPLIT, indicates that this is a to-home animation. */
static final int ANIM_TYPE_GOING_HOME = 1;
- /** For RECENTS_DURING_SPLIT, is set when this turns into a pair->pair task switch. */
- static final int ANIM_TYPE_PAIR_TO_PAIR = 1;
-
final int mType;
- int mAnimType = ANIM_TYPE_DEFAULT;
+ int mAnimType = 0;
final IBinder mTransition;
Transitions.TransitionHandler mLeftoversHandler = null;
@@ -175,25 +167,6 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler {
mixed.mLeftoversHandler = handler.first;
mActiveTransitions.add(mixed);
return handler.second;
- } else if (mSplitHandler.isSplitActive()
- && isOpeningType(request.getType())
- && request.getTriggerTask() != null
- && request.getTriggerTask().getWindowingMode() == WINDOWING_MODE_FULLSCREEN
- && (request.getTriggerTask().getActivityType() == ACTIVITY_TYPE_HOME
- || request.getTriggerTask().getActivityType() == ACTIVITY_TYPE_RECENTS)) {
- ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Got a recents request while "
- + "Split-Screen is active, so treat it as Mixed.");
- Pair<Transitions.TransitionHandler, WindowContainerTransaction> handler =
- mPlayer.dispatchRequest(transition, request, this);
- if (handler == null) {
- // fall through -- it will probably be picked-up by normal split handler.
- return null;
- }
- final MixedTransition mixed = new MixedTransition(
- MixedTransition.TYPE_RECENTS_DURING_SPLIT, transition);
- mixed.mLeftoversHandler = handler.first;
- mActiveTransitions.add(mixed);
- return handler.second;
}
return null;
}
@@ -241,9 +214,6 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler {
} else if (mixed.mType == MixedTransition.TYPE_OPTIONS_REMOTE_AND_PIP_CHANGE) {
return animateOpenIntentWithRemoteAndPip(mixed, info, startTransaction,
finishTransaction, finishCallback);
- } else if (mixed.mType == MixedTransition.TYPE_RECENTS_DURING_SPLIT) {
- return animateRecentsDuringSplit(mixed, info, startTransaction, finishTransaction,
- finishCallback);
} else {
mActiveTransitions.remove(mixed);
throw new IllegalStateException("Starting mixed animation without a known mixed type? "
@@ -469,40 +439,12 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler {
return true;
}
- private boolean animateRecentsDuringSplit(@NonNull final MixedTransition mixed,
- @NonNull TransitionInfo info,
- @NonNull SurfaceControl.Transaction startTransaction,
- @NonNull SurfaceControl.Transaction finishTransaction,
- @NonNull Transitions.TransitionFinishCallback finishCallback) {
- // Split-screen is only interested in the recents transition finishing (and merging), so
- // just wrap finish and start recents animation directly.
- Transitions.TransitionFinishCallback finishCB = (wct, wctCB) -> {
- 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);
- }
- mSplitHandler.onTransitionAnimationComplete();
- finishCallback.onTransitionFinished(wct, wctCB);
- };
- mixed.mInFlightSubAnimations = 1;
- mSplitHandler.onRecentsInSplitAnimationStart(startTransaction);
- final boolean handled = mixed.mLeftoversHandler.startAnimation(mixed.mTransition, info,
- startTransaction, finishTransaction, finishCB);
- if (!handled) {
- mActiveTransitions.remove(mixed);
- }
- return handled;
- }
-
@Override
public void mergeAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
@NonNull SurfaceControl.Transaction t, @NonNull IBinder mergeTarget,
@NonNull Transitions.TransitionFinishCallback finishCallback) {
for (int i = 0; i < mActiveTransitions.size(); ++i) {
- if (mActiveTransitions.get(i).mTransition != mergeTarget) continue;
+ if (mActiveTransitions.get(i) != mergeTarget) continue;
MixedTransition mixed = mActiveTransitions.get(i);
if (mixed.mInFlightSubAnimations <= 0) {
// Already done, so no need to end it.
@@ -530,14 +472,6 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler {
mixed.mLeftoversHandler.mergeAnimation(transition, info, t, mergeTarget,
finishCallback);
}
- } else if (mixed.mType == MixedTransition.TYPE_RECENTS_DURING_SPLIT) {
- if (mSplitHandler.isPendingEnter(transition)) {
- // Recents -> enter-split means that we are switching from one pair to
- // another pair.
- mixed.mAnimType = MixedTransition.ANIM_TYPE_PAIR_TO_PAIR;
- }
- mixed.mLeftoversHandler.mergeAnimation(transition, info, t, mergeTarget,
- finishCallback);
} else {
throw new IllegalStateException("Playing a mixed transition with unknown type? "
+ mixed.mType);
@@ -557,8 +491,6 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler {
if (mixed == null) return;
if (mixed.mType == MixedTransition.TYPE_ENTER_PIP_FROM_SPLIT) {
mPipHandler.onTransitionConsumed(transition, aborted, finishT);
- } else if (mixed.mType == MixedTransition.TYPE_RECENTS_DURING_SPLIT) {
- mixed.mLeftoversHandler.onTransitionConsumed(transition, aborted, finishT);
}
}
}
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 2edec7db828f..3901dabcaec8 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
@@ -35,7 +35,6 @@ import static com.android.wm.shell.transition.Transitions.TRANSIT_SPLIT_SCREEN_P
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -250,7 +249,7 @@ public class SplitTransitionTests extends ShellTestCase {
@Test
@UiThreadTest
- public void testEnterRecentsAndCommit() {
+ public void testEnterRecents() {
enterSplit();
ActivityManager.RunningTaskInfo homeTask = new TestRunningTaskInfoBuilder()
@@ -262,60 +261,24 @@ public class SplitTransitionTests extends ShellTestCase {
TransitionRequestInfo request = new TransitionRequestInfo(TRANSIT_TO_FRONT, homeTask, null);
IBinder transition = mock(IBinder.class);
WindowContainerTransaction result = mStageCoordinator.handleRequest(transition, request);
- // Don't handle recents opening
- assertNull(result);
- // make sure we haven't made any local changes yet (need to wait until transition is ready)
- assertTrue(mStageCoordinator.isSplitScreenVisible());
-
- // simulate the start of recents transition
- mMainStage.onTaskVanished(mMainChild);
- mSideStage.onTaskVanished(mSideChild);
- mStageCoordinator.onRecentsInSplitAnimationStart(mock(SurfaceControl.Transaction.class));
- assertTrue(mStageCoordinator.isSplitScreenVisible());
-
- // Make sure it cleans-up if recents doesn't restore
- WindowContainerTransaction commitWCT = new WindowContainerTransaction();
- mStageCoordinator.onRecentsInSplitAnimationFinish(commitWCT,
- mock(SurfaceControl.Transaction.class));
- assertFalse(mStageCoordinator.isSplitScreenVisible());
- }
-
- @Test
- @UiThreadTest
- public void testEnterRecentsAndRestore() {
- enterSplit();
-
- ActivityManager.RunningTaskInfo homeTask = new TestRunningTaskInfoBuilder()
- .setWindowingMode(WINDOWING_MODE_FULLSCREEN)
- .setActivityType(ACTIVITY_TYPE_HOME)
- .build();
-
- // Create a request to bring home forward
- TransitionRequestInfo request = new TransitionRequestInfo(TRANSIT_TO_FRONT, homeTask, null);
- IBinder transition = mock(IBinder.class);
- WindowContainerTransaction result = mStageCoordinator.handleRequest(transition, request);
- // Don't handle recents opening
- assertNull(result);
+ assertTrue(result.isEmpty());
// make sure we haven't made any local changes yet (need to wait until transition is ready)
assertTrue(mStageCoordinator.isSplitScreenVisible());
- // simulate the start of recents transition
+ // simulate the transition
+ TransitionInfo info = new TransitionInfoBuilder(TRANSIT_TO_FRONT, 0)
+ .addChange(TRANSIT_TO_FRONT, homeTask)
+ .addChange(TRANSIT_TO_BACK, mMainChild)
+ .addChange(TRANSIT_TO_BACK, mSideChild)
+ .build();
mMainStage.onTaskVanished(mMainChild);
mSideStage.onTaskVanished(mSideChild);
- mStageCoordinator.onRecentsInSplitAnimationStart(mock(SurfaceControl.Transaction.class));
- assertTrue(mStageCoordinator.isSplitScreenVisible());
-
- // Make sure we remain in split after recents restores.
- WindowContainerTransaction restoreWCT = new WindowContainerTransaction();
- restoreWCT.reorder(mMainChild.token, true /* toTop */);
- restoreWCT.reorder(mSideChild.token, true /* toTop */);
- // simulate the restoreWCT being applied:
- mMainStage.onTaskAppeared(mMainChild, mock(SurfaceControl.class));
- mSideStage.onTaskAppeared(mSideChild, mock(SurfaceControl.class));
- mStageCoordinator.onRecentsInSplitAnimationFinish(restoreWCT,
- mock(SurfaceControl.Transaction.class));
+ mStageCoordinator.startAnimation(transition, info,
+ mock(SurfaceControl.Transaction.class),
+ mock(SurfaceControl.Transaction.class),
+ mock(Transitions.TransitionFinishCallback.class));
assertTrue(mStageCoordinator.isSplitScreenVisible());
}