summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java42
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java50
2 files changed, 59 insertions, 33 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 8664d9be3340..d30d0cc95f46 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
@@ -70,7 +70,8 @@ class SplitScreenTransitions {
IBinder mPendingRecent = null;
private IBinder mAnimatingTransition = null;
- private OneShotRemoteHandler mRemoteHandler = null;
+ private OneShotRemoteHandler mPendingRemoteHandler = null;
+ private OneShotRemoteHandler mActiveRemoteHandler = null;
private final Transitions.TransitionFinishCallback mRemoteFinishCB = this::onFinish;
@@ -96,10 +97,11 @@ class SplitScreenTransitions {
@NonNull WindowContainerToken mainRoot, @NonNull WindowContainerToken sideRoot) {
mFinishCallback = finishCallback;
mAnimatingTransition = transition;
- if (mRemoteHandler != null) {
- mRemoteHandler.startAnimation(transition, info, startTransaction, finishTransaction,
- mRemoteFinishCB);
- mRemoteHandler = null;
+ if (mPendingRemoteHandler != null) {
+ mPendingRemoteHandler.startAnimation(transition, info, startTransaction,
+ finishTransaction, mRemoteFinishCB);
+ mActiveRemoteHandler = mPendingRemoteHandler;
+ mPendingRemoteHandler = null;
return;
}
playInternalAnimation(transition, info, startTransaction, mainRoot, sideRoot);
@@ -172,15 +174,14 @@ class SplitScreenTransitions {
IBinder startEnterTransition(@WindowManager.TransitionType int transitType,
@NonNull WindowContainerTransaction wct, @Nullable RemoteTransition remoteTransition,
@NonNull Transitions.TransitionHandler handler) {
+ final IBinder transition = mTransitions.startTransition(transitType, wct, handler);
+ mPendingEnter = transition;
+
if (remoteTransition != null) {
// Wrapping it for ease-of-use (OneShot handles all the binder linking/death stuff)
- mRemoteHandler = new OneShotRemoteHandler(
+ mPendingRemoteHandler = new OneShotRemoteHandler(
mTransitions.getMainExecutor(), remoteTransition);
- }
- final IBinder transition = mTransitions.startTransition(transitType, wct, handler);
- mPendingEnter = transition;
- if (mRemoteHandler != null) {
- mRemoteHandler.setTransition(transition);
+ mPendingRemoteHandler.setTransition(transition);
}
return transition;
}
@@ -211,9 +212,9 @@ class SplitScreenTransitions {
if (remoteTransition != null) {
// Wrapping it for ease-of-use (OneShot handles all the binder linking/death stuff)
- mRemoteHandler = new OneShotRemoteHandler(
+ mPendingRemoteHandler = new OneShotRemoteHandler(
mTransitions.getMainExecutor(), remoteTransition);
- mRemoteHandler.setTransition(transition);
+ mPendingRemoteHandler.setTransition(transition);
}
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " splitTransition "
@@ -221,6 +222,13 @@ class SplitScreenTransitions {
return transition;
}
+ void mergeAnimation(IBinder transition, TransitionInfo info, SurfaceControl.Transaction t,
+ IBinder mergeTarget, Transitions.TransitionFinishCallback finishCallback) {
+ if (mergeTarget == mAnimatingTransition && mActiveRemoteHandler != null) {
+ mActiveRemoteHandler.mergeAnimation(transition, info, t, mergeTarget, finishCallback);
+ }
+ }
+
void onFinish(WindowContainerTransaction wct, WindowContainerTransactionCallback wctCB) {
if (!mAnimations.isEmpty()) return;
mOnFinish.run();
@@ -241,11 +249,13 @@ class SplitScreenTransitions {
}
if (mAnimatingTransition == mPendingRecent) {
// If the wct is not null while finishing recent transition, it indicates it's not
- // returning to home and hence needing the wct to reorder tasks.
- final boolean toHome = wct == null;
- mStageCoordinator.finishRecentAnimation(toHome);
+ // dismissing split and thus need to reorder split task so they can be on top again.
+ final boolean dismissSplit = wct == null;
+ mStageCoordinator.finishRecentAnimation(dismissSplit);
mPendingRecent = null;
}
+ mPendingRemoteHandler = null;
+ mActiveRemoteHandler = null;
mAnimatingTransition = null;
}
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 c8120509f0db..e592101d2b20 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
@@ -166,17 +166,6 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
@StageType
private int mTopStageAfterFoldDismiss = STAGE_TYPE_UNDEFINED;
- private final Runnable mOnTransitionAnimationComplete = () -> {
- // If still playing, let it finish.
- if (!isSplitScreenVisible()) {
- // Update divider state after animation so that it is still around and positioned
- // properly for the animation itself.
- mSplitLayout.release();
- mSplitLayout.resetDividerPosition();
- mTopStageAfterFoldDismiss = STAGE_TYPE_UNDEFINED;
- }
- };
-
private final SplitWindowManager.ParentContainerCallbacks mParentContainerCallbacks =
new SplitWindowManager.ParentContainerCallbacks() {
@Override
@@ -237,7 +226,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
deviceStateManager.registerCallback(taskOrganizer.getExecutor(),
new DeviceStateManager.FoldStateListener(mContext, this::onFoldedStateChanged));
mSplitTransitions = new SplitScreenTransitions(transactionPool, transitions,
- mOnTransitionAnimationComplete, this);
+ this::onTransitionAnimationComplete, this);
mDisplayController.addDisplayWindowListener(this);
mDisplayLayout = new DisplayLayout(displayController.getDisplayLayout(displayId));
transitions.addHandler(this);
@@ -267,7 +256,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mRootTDAOrganizer.registerListener(displayId, this);
mSplitLayout = splitLayout;
mSplitTransitions = new SplitScreenTransitions(transactionPool, transitions,
- mOnTransitionAnimationComplete, this);
+ this::onTransitionAnimationComplete, this);
mMainUnfoldController = unfoldControllerProvider.get().orElse(null);
mSideUnfoldController = unfoldControllerProvider.get().orElse(null);
mLogger = logger;
@@ -1234,7 +1223,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
final ActivityManager.RunningTaskInfo triggerTask = request.getTriggerTask();
if (triggerTask == null) {
// Still want to monitor everything while in split-screen, so return non-null.
- return isSplitScreenVisible() ? new WindowContainerTransaction() : null;
+ return mMainStage.isActive() ? new WindowContainerTransaction() : null;
} else if (triggerTask.displayId != mDisplayId) {
// Skip handling task on the other display.
return null;
@@ -1250,7 +1239,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mRecentTasks.ifPresent(recentTasks -> recentTasks.removeSplitPair(triggerTask.taskId));
}
- if (isSplitScreenVisible()) {
+ if (mMainStage.isActive()) {
// Try to handle everything while in split-screen, so return a WCT even if it's empty.
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " split is active so using split"
+ "Transition to handle request. triggerTask=%d type=%s mainChildren=%d"
@@ -1296,6 +1285,13 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
}
@Override
+ public void mergeAnimation(IBinder transition, TransitionInfo info,
+ SurfaceControl.Transaction t, IBinder mergeTarget,
+ Transitions.TransitionFinishCallback finishCallback) {
+ mSplitTransitions.mergeAnimation(transition, info, t, mergeTarget, finishCallback);
+ }
+
+ @Override
public void onTransitionMerged(@NonNull IBinder transition) {
// Once the pending enter transition got merged, make sure to bring divider bar visible and
// clear the pending transition from cache to prevent mess-up the following state.
@@ -1375,6 +1371,17 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
return true;
}
+ void onTransitionAnimationComplete() {
+ // If still playing, let it finish.
+ if (!mMainStage.isActive()) {
+ // Update divider state after animation so that it is still around and positioned
+ // properly for the animation itself.
+ mSplitLayout.release();
+ mSplitLayout.resetDividerPosition();
+ mTopStageAfterFoldDismiss = STAGE_TYPE_UNDEFINED;
+ }
+ }
+
private boolean startPendingEnterAnimation(@NonNull IBinder transition,
@NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction t) {
// First, verify that we actually have opened apps in both splits.
@@ -1513,8 +1520,17 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
return true;
}
- void finishRecentAnimation(boolean toHome) {
- if (toHome) {
+ void finishRecentAnimation(boolean dismissSplit) {
+ // Exclude the case that the split screen has been dismissed already.
+ if (!mMainStage.isActive()) {
+ // The latest split dismissing transition might be a no-op transition and thus won't
+ // callback startAnimation, update split visibility here to cover this kind of no-op
+ // transition case.
+ setSplitsVisible(false);
+ return;
+ }
+
+ if (dismissSplit) {
final WindowContainerTransaction wct = new WindowContainerTransaction();
prepareExitSplitScreen(STAGE_TYPE_UNDEFINED, wct);
mSplitTransitions.startDismissTransition(null /* transition */, wct, this,