Loading libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java +6 −0 Original line number Diff line number Diff line Loading @@ -293,6 +293,9 @@ public class SplitDecorManager extends WindowlessWindowManager { } if (mResizingIconView == null) { if (mRunningAnimationCount == 0 && animFinishedCallback != null) { animFinishedCallback.accept(false); } return; } Loading @@ -311,6 +314,9 @@ public class SplitDecorManager extends WindowlessWindowManager { releaseDecor(finishT); finishT.apply(); finishT.close(); if (mRunningAnimationCount == 0 && animFinishedCallback != null) { animFinishedCallback.accept(true); } } }); return; Loading libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java +49 −6 Original line number Diff line number Diff line Loading @@ -87,6 +87,14 @@ class SplitScreenTransitions { mStageCoordinator = stageCoordinator; } private void initTransition(@NonNull IBinder transition, @NonNull SurfaceControl.Transaction finishTransaction, @NonNull Transitions.TransitionFinishCallback finishCallback) { mAnimatingTransition = transition; mFinishTransaction = finishTransaction; mFinishCallback = finishCallback; } /** Play animation for enter transition or dismiss transition. */ void playAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction startTransaction, Loading @@ -94,9 +102,7 @@ class SplitScreenTransitions { @NonNull Transitions.TransitionFinishCallback finishCallback, @NonNull WindowContainerToken mainRoot, @NonNull WindowContainerToken sideRoot, @NonNull WindowContainerToken topRoot) { mFinishCallback = finishCallback; mAnimatingTransition = transition; mFinishTransaction = finishTransaction; initTransition(transition, finishTransaction, finishCallback); final TransitSession pendingTransition = getPendingTransition(transition); if (pendingTransition != null) { Loading Loading @@ -220,6 +226,45 @@ class SplitScreenTransitions { onFinish(null /* wct */, null /* wctCB */); } /** Play animation for drag divider dismiss transition. */ void playDragDismissAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction startTransaction, @NonNull SurfaceControl.Transaction finishTransaction, @NonNull Transitions.TransitionFinishCallback finishCallback, @NonNull WindowContainerToken toTopRoot, @NonNull SplitDecorManager toTopDecor, @NonNull WindowContainerToken topRoot) { initTransition(transition, finishTransaction, finishCallback); for (int i = info.getChanges().size() - 1; i >= 0; --i) { final TransitionInfo.Change change = info.getChanges().get(i); final SurfaceControl leash = change.getLeash(); if (toTopRoot.equals(change.getContainer())) { startTransaction.setAlpha(leash, 1.f); startTransaction.show(leash); ValueAnimator va = new ValueAnimator(); mAnimations.add(va); toTopDecor.onResized(startTransaction, animated -> { mAnimations.remove(va); if (animated) { mTransitions.getMainExecutor().execute(() -> { onFinish(null /* wct */, null /* wctCB */); }); } }); } else if (topRoot.equals(change.getContainer())) { // Ensure it on top of all changes in transition. startTransaction.setLayer(leash, Integer.MAX_VALUE); startTransaction.setAlpha(leash, 1.f); startTransaction.show(leash); } } startTransaction.apply(); onFinish(null /* wct */, null /* wctCB */); } /** Play animation for resize transition. */ void playResizeAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction startTransaction, Loading @@ -227,9 +272,7 @@ class SplitScreenTransitions { @NonNull Transitions.TransitionFinishCallback finishCallback, @NonNull WindowContainerToken mainRoot, @NonNull WindowContainerToken sideRoot, @NonNull SplitDecorManager mainDecor, @NonNull SplitDecorManager sideDecor) { mFinishCallback = finishCallback; mAnimatingTransition = transition; mFinishTransaction = finishTransaction; initTransition(transition, finishTransaction, finishCallback); for (int i = info.getChanges().size() - 1; i >= 0; --i) { final TransitionInfo.Change change = info.getChanges().get(i); Loading libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +21 −4 Original line number Diff line number Diff line Loading @@ -1328,8 +1328,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, mIsExiting = true; childrenToTop.resetBounds(wct); wct.reorder(childrenToTop.mRootTaskInfo.token, true); wct.setSmallestScreenWidthDp(childrenToTop.mRootTaskInfo.token, SMALLEST_SCREEN_WIDTH_DP_UNDEFINED); } wct.setReparentLeafTaskIfRelaunch(mRootTaskInfo.token, false /* reparentLeafTaskIfRelaunch */); Loading Loading @@ -1517,6 +1515,10 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, void finishEnterSplitScreen(SurfaceControl.Transaction t) { mSplitLayout.update(t); mMainStage.getSplitDecorManager().inflate(mContext, mMainStage.mRootLeash, getMainStageBounds()); mSideStage.getSplitDecorManager().inflate(mContext, mSideStage.mRootLeash, getSideStageBounds()); setDividerVisibility(true, t); // Ensure divider surface are re-parented back into the hierarchy at the end of the // transition. See Transition#buildFinishTransaction for more detail. Loading Loading @@ -1989,13 +1991,15 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, final boolean mainStageToTop = bottomOrRight ? mSideStagePosition == SPLIT_POSITION_BOTTOM_OR_RIGHT : mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT; final StageTaskListener toTopStage = mainStageToTop ? mMainStage : mSideStage; if (!ENABLE_SHELL_TRANSITIONS) { exitSplitScreen(mainStageToTop ? mMainStage : mSideStage, reason); exitSplitScreen(toTopStage, reason); return; } final int dismissTop = mainStageToTop ? STAGE_TYPE_MAIN : STAGE_TYPE_SIDE; final WindowContainerTransaction wct = new WindowContainerTransaction(); toTopStage.resetBounds(wct); prepareExitSplitScreen(dismissTop, wct); if (mRootTaskInfo != null) { wct.setDoNotPip(mRootTaskInfo.token); Loading Loading @@ -2531,8 +2535,17 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, shouldAnimate = startPendingEnterAnimation( mSplitTransitions.mPendingEnter, info, startTransaction, finishTransaction); } else if (mSplitTransitions.isPendingDismiss(transition)) { final SplitScreenTransitions.DismissSession dismiss = mSplitTransitions.mPendingDismiss; shouldAnimate = startPendingDismissAnimation( mSplitTransitions.mPendingDismiss, info, startTransaction, finishTransaction); dismiss, info, startTransaction, finishTransaction); if (shouldAnimate && dismiss.mReason == EXIT_REASON_DRAG_DIVIDER) { final StageTaskListener toTopStage = dismiss.mDismissTop == STAGE_TYPE_MAIN ? mMainStage : mSideStage; mSplitTransitions.playDragDismissAnimation(transition, info, startTransaction, finishTransaction, finishCallback, toTopStage.mRootTaskInfo.token, toTopStage.getSplitDecorManager(), mRootTaskInfo.token); return true; } } else if (mSplitTransitions.isPendingResize(transition)) { mSplitTransitions.playResizeAnimation(transition, info, startTransaction, finishTransaction, finishCallback, mMainStage.mRootTaskInfo.token, Loading Loading @@ -2787,6 +2800,10 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, mSplitTransitions.mPendingDismiss = null; return false; } dismissTransition.setFinishedCallback((callbackWct, callbackT) -> { mMainStage.getSplitDecorManager().release(callbackT); mSideStage.getSplitDecorManager().release(callbackT); }); addDividerBarToTransition(info, false /* show */); return true; Loading libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java +3 −1 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.wm.shell.splitscreen; import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.content.res.Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED; import static android.view.RemoteAnimationTarget.MODE_OPENING; import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_ACTIVITY_TYPES; Loading Loading @@ -201,7 +202,7 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener { public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) { if (mRootTaskInfo.taskId == taskInfo.taskId) { // Inflates split decor view only when the root task is visible. if (mRootTaskInfo.isVisible != taskInfo.isVisible) { if (!ENABLE_SHELL_TRANSITIONS && mRootTaskInfo.isVisible != taskInfo.isVisible) { if (taskInfo.isVisible) { mSplitDecorManager.inflate(mContext, mRootLeash, taskInfo.configuration.windowConfiguration.getBounds()); Loading Loading @@ -385,6 +386,7 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener { void resetBounds(WindowContainerTransaction wct) { wct.setBounds(mRootTaskInfo.token, null); wct.setAppBounds(mRootTaskInfo.token, null); wct.setSmallestScreenWidthDp(mRootTaskInfo.token, SMALLEST_SCREEN_WIDTH_DP_UNDEFINED); } void onSplitScreenListenerRegistered(SplitScreen.SplitScreenListener listener, Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTestUtils.java +4 −0 Original line number Diff line number Diff line Loading @@ -44,11 +44,15 @@ public class SplitTestUtils { static SplitLayout createMockSplitLayout() { final Rect dividerBounds = new Rect(48, 0, 52, 100); final Rect bounds1 = new Rect(0, 0, 40, 100); final Rect bounds2 = new Rect(60, 0, 100, 100); final SurfaceControl leash = createMockSurface(); SplitLayout out = mock(SplitLayout.class); doReturn(dividerBounds).when(out).getDividerBounds(); doReturn(dividerBounds).when(out).getRefDividerBounds(); doReturn(leash).when(out).getDividerLeash(); doReturn(bounds1).when(out).getBounds1(); doReturn(bounds2).when(out).getBounds2(); return out; } Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java +6 −0 Original line number Diff line number Diff line Loading @@ -293,6 +293,9 @@ public class SplitDecorManager extends WindowlessWindowManager { } if (mResizingIconView == null) { if (mRunningAnimationCount == 0 && animFinishedCallback != null) { animFinishedCallback.accept(false); } return; } Loading @@ -311,6 +314,9 @@ public class SplitDecorManager extends WindowlessWindowManager { releaseDecor(finishT); finishT.apply(); finishT.close(); if (mRunningAnimationCount == 0 && animFinishedCallback != null) { animFinishedCallback.accept(true); } } }); return; Loading
libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java +49 −6 Original line number Diff line number Diff line Loading @@ -87,6 +87,14 @@ class SplitScreenTransitions { mStageCoordinator = stageCoordinator; } private void initTransition(@NonNull IBinder transition, @NonNull SurfaceControl.Transaction finishTransaction, @NonNull Transitions.TransitionFinishCallback finishCallback) { mAnimatingTransition = transition; mFinishTransaction = finishTransaction; mFinishCallback = finishCallback; } /** Play animation for enter transition or dismiss transition. */ void playAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction startTransaction, Loading @@ -94,9 +102,7 @@ class SplitScreenTransitions { @NonNull Transitions.TransitionFinishCallback finishCallback, @NonNull WindowContainerToken mainRoot, @NonNull WindowContainerToken sideRoot, @NonNull WindowContainerToken topRoot) { mFinishCallback = finishCallback; mAnimatingTransition = transition; mFinishTransaction = finishTransaction; initTransition(transition, finishTransaction, finishCallback); final TransitSession pendingTransition = getPendingTransition(transition); if (pendingTransition != null) { Loading Loading @@ -220,6 +226,45 @@ class SplitScreenTransitions { onFinish(null /* wct */, null /* wctCB */); } /** Play animation for drag divider dismiss transition. */ void playDragDismissAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction startTransaction, @NonNull SurfaceControl.Transaction finishTransaction, @NonNull Transitions.TransitionFinishCallback finishCallback, @NonNull WindowContainerToken toTopRoot, @NonNull SplitDecorManager toTopDecor, @NonNull WindowContainerToken topRoot) { initTransition(transition, finishTransaction, finishCallback); for (int i = info.getChanges().size() - 1; i >= 0; --i) { final TransitionInfo.Change change = info.getChanges().get(i); final SurfaceControl leash = change.getLeash(); if (toTopRoot.equals(change.getContainer())) { startTransaction.setAlpha(leash, 1.f); startTransaction.show(leash); ValueAnimator va = new ValueAnimator(); mAnimations.add(va); toTopDecor.onResized(startTransaction, animated -> { mAnimations.remove(va); if (animated) { mTransitions.getMainExecutor().execute(() -> { onFinish(null /* wct */, null /* wctCB */); }); } }); } else if (topRoot.equals(change.getContainer())) { // Ensure it on top of all changes in transition. startTransaction.setLayer(leash, Integer.MAX_VALUE); startTransaction.setAlpha(leash, 1.f); startTransaction.show(leash); } } startTransaction.apply(); onFinish(null /* wct */, null /* wctCB */); } /** Play animation for resize transition. */ void playResizeAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction startTransaction, Loading @@ -227,9 +272,7 @@ class SplitScreenTransitions { @NonNull Transitions.TransitionFinishCallback finishCallback, @NonNull WindowContainerToken mainRoot, @NonNull WindowContainerToken sideRoot, @NonNull SplitDecorManager mainDecor, @NonNull SplitDecorManager sideDecor) { mFinishCallback = finishCallback; mAnimatingTransition = transition; mFinishTransaction = finishTransaction; initTransition(transition, finishTransaction, finishCallback); for (int i = info.getChanges().size() - 1; i >= 0; --i) { final TransitionInfo.Change change = info.getChanges().get(i); Loading
libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +21 −4 Original line number Diff line number Diff line Loading @@ -1328,8 +1328,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, mIsExiting = true; childrenToTop.resetBounds(wct); wct.reorder(childrenToTop.mRootTaskInfo.token, true); wct.setSmallestScreenWidthDp(childrenToTop.mRootTaskInfo.token, SMALLEST_SCREEN_WIDTH_DP_UNDEFINED); } wct.setReparentLeafTaskIfRelaunch(mRootTaskInfo.token, false /* reparentLeafTaskIfRelaunch */); Loading Loading @@ -1517,6 +1515,10 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, void finishEnterSplitScreen(SurfaceControl.Transaction t) { mSplitLayout.update(t); mMainStage.getSplitDecorManager().inflate(mContext, mMainStage.mRootLeash, getMainStageBounds()); mSideStage.getSplitDecorManager().inflate(mContext, mSideStage.mRootLeash, getSideStageBounds()); setDividerVisibility(true, t); // Ensure divider surface are re-parented back into the hierarchy at the end of the // transition. See Transition#buildFinishTransaction for more detail. Loading Loading @@ -1989,13 +1991,15 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, final boolean mainStageToTop = bottomOrRight ? mSideStagePosition == SPLIT_POSITION_BOTTOM_OR_RIGHT : mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT; final StageTaskListener toTopStage = mainStageToTop ? mMainStage : mSideStage; if (!ENABLE_SHELL_TRANSITIONS) { exitSplitScreen(mainStageToTop ? mMainStage : mSideStage, reason); exitSplitScreen(toTopStage, reason); return; } final int dismissTop = mainStageToTop ? STAGE_TYPE_MAIN : STAGE_TYPE_SIDE; final WindowContainerTransaction wct = new WindowContainerTransaction(); toTopStage.resetBounds(wct); prepareExitSplitScreen(dismissTop, wct); if (mRootTaskInfo != null) { wct.setDoNotPip(mRootTaskInfo.token); Loading Loading @@ -2531,8 +2535,17 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, shouldAnimate = startPendingEnterAnimation( mSplitTransitions.mPendingEnter, info, startTransaction, finishTransaction); } else if (mSplitTransitions.isPendingDismiss(transition)) { final SplitScreenTransitions.DismissSession dismiss = mSplitTransitions.mPendingDismiss; shouldAnimate = startPendingDismissAnimation( mSplitTransitions.mPendingDismiss, info, startTransaction, finishTransaction); dismiss, info, startTransaction, finishTransaction); if (shouldAnimate && dismiss.mReason == EXIT_REASON_DRAG_DIVIDER) { final StageTaskListener toTopStage = dismiss.mDismissTop == STAGE_TYPE_MAIN ? mMainStage : mSideStage; mSplitTransitions.playDragDismissAnimation(transition, info, startTransaction, finishTransaction, finishCallback, toTopStage.mRootTaskInfo.token, toTopStage.getSplitDecorManager(), mRootTaskInfo.token); return true; } } else if (mSplitTransitions.isPendingResize(transition)) { mSplitTransitions.playResizeAnimation(transition, info, startTransaction, finishTransaction, finishCallback, mMainStage.mRootTaskInfo.token, Loading Loading @@ -2787,6 +2800,10 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, mSplitTransitions.mPendingDismiss = null; return false; } dismissTransition.setFinishedCallback((callbackWct, callbackT) -> { mMainStage.getSplitDecorManager().release(callbackT); mSideStage.getSplitDecorManager().release(callbackT); }); addDividerBarToTransition(info, false /* show */); return true; Loading
libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java +3 −1 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.wm.shell.splitscreen; import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.content.res.Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED; import static android.view.RemoteAnimationTarget.MODE_OPENING; import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_ACTIVITY_TYPES; Loading Loading @@ -201,7 +202,7 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener { public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) { if (mRootTaskInfo.taskId == taskInfo.taskId) { // Inflates split decor view only when the root task is visible. if (mRootTaskInfo.isVisible != taskInfo.isVisible) { if (!ENABLE_SHELL_TRANSITIONS && mRootTaskInfo.isVisible != taskInfo.isVisible) { if (taskInfo.isVisible) { mSplitDecorManager.inflate(mContext, mRootLeash, taskInfo.configuration.windowConfiguration.getBounds()); Loading Loading @@ -385,6 +386,7 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener { void resetBounds(WindowContainerTransaction wct) { wct.setBounds(mRootTaskInfo.token, null); wct.setAppBounds(mRootTaskInfo.token, null); wct.setSmallestScreenWidthDp(mRootTaskInfo.token, SMALLEST_SCREEN_WIDTH_DP_UNDEFINED); } void onSplitScreenListenerRegistered(SplitScreen.SplitScreenListener listener, Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTestUtils.java +4 −0 Original line number Diff line number Diff line Loading @@ -44,11 +44,15 @@ public class SplitTestUtils { static SplitLayout createMockSplitLayout() { final Rect dividerBounds = new Rect(48, 0, 52, 100); final Rect bounds1 = new Rect(0, 0, 40, 100); final Rect bounds2 = new Rect(60, 0, 100, 100); final SurfaceControl leash = createMockSurface(); SplitLayout out = mock(SplitLayout.class); doReturn(dividerBounds).when(out).getDividerBounds(); doReturn(dividerBounds).when(out).getRefDividerBounds(); doReturn(leash).when(out).getDividerLeash(); doReturn(bounds1).when(out).getBounds1(); doReturn(bounds2).when(out).getBounds2(); return out; } Loading