Loading libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java +26 −16 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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); Loading Loading @@ -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; } Loading Loading @@ -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 " Loading @@ -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(); Loading @@ -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; } Loading libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +33 −17 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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); Loading Loading @@ -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; Loading Loading @@ -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; Loading @@ -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" Loading Loading @@ -1295,6 +1284,13 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, return out; } @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 Loading Loading @@ -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. Loading Loading @@ -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, Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java +26 −16 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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); Loading Loading @@ -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; } Loading Loading @@ -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 " Loading @@ -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(); Loading @@ -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; } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +33 −17 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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); Loading Loading @@ -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; Loading Loading @@ -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; Loading @@ -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" Loading Loading @@ -1295,6 +1284,13 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, return out; } @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 Loading Loading @@ -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. Loading Loading @@ -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, Loading