diff options
| -rw-r--r-- | libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java | 42 | ||||
| -rw-r--r-- | libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java | 50 |
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, |