Loading libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java +32 −0 Original line number Original line Diff line number Diff line Loading @@ -68,6 +68,7 @@ class SplitScreenTransitions { DismissSession mPendingDismiss = null; DismissSession mPendingDismiss = null; EnterSession mPendingEnter = null; EnterSession mPendingEnter = null; TransitSession mPendingResize = null; TransitSession mPendingResize = null; TransitSession mPendingRemotePassthrough = null; private IBinder mAnimatingTransition = null; private IBinder mAnimatingTransition = null; private OneShotRemoteHandler mActiveRemoteHandler = null; private OneShotRemoteHandler mActiveRemoteHandler = null; Loading Loading @@ -320,6 +321,11 @@ class SplitScreenTransitions { return mPendingResize != null && mPendingResize.mTransition == transition; return mPendingResize != null && mPendingResize.mTransition == transition; } } boolean isPendingPassThrough(IBinder transition) { return mPendingRemotePassthrough != null && mPendingRemotePassthrough.mTransition == transition; } @Nullable @Nullable private TransitSession getPendingTransition(IBinder transition) { private TransitSession getPendingTransition(IBinder transition) { if (isPendingEnter(transition)) { if (isPendingEnter(transition)) { Loading @@ -331,6 +337,9 @@ class SplitScreenTransitions { } else if (isPendingResize(transition)) { } else if (isPendingResize(transition)) { ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "\tresolved resize transition"); ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "\tresolved resize transition"); return mPendingResize; return mPendingResize; } else if (isPendingPassThrough(transition)) { ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "\tresolved passThrough transition"); return mPendingRemotePassthrough; } } return null; return null; } } Loading Loading @@ -378,6 +387,19 @@ class SplitScreenTransitions { extraTransitType, resizeAnim); extraTransitType, resizeAnim); } } /** Sets a transition to enter split. */ void setRemotePassThroughTransition(@NonNull IBinder transition, @Nullable RemoteTransition remoteTransition) { mPendingRemotePassthrough = new TransitSession( transition, null, null, remoteTransition, Transitions.TRANSIT_SPLIT_PASSTHROUGH); ProtoLog.v(WM_SHELL_TRANSITIONS, " splitTransition " + " deduced remote passthrough split screen"); ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "setRemotePassThrough: transitType=%d remote=%s", Transitions.TRANSIT_SPLIT_PASSTHROUGH, remoteTransition); } /** Starts a transition to dismiss split. */ /** Starts a transition to dismiss split. */ IBinder startDismissTransition(WindowContainerTransaction wct, IBinder startDismissTransition(WindowContainerTransaction wct, Transitions.TransitionHandler handler, @SplitScreen.StageType int dismissTop, Transitions.TransitionHandler handler, @SplitScreen.StageType int dismissTop, Loading Loading @@ -474,6 +496,12 @@ class SplitScreenTransitions { mPendingResize.onConsumed(aborted); mPendingResize.onConsumed(aborted); mPendingResize = null; mPendingResize = null; ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "onTransitionConsumed for resize transition"); ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "onTransitionConsumed for resize transition"); } else if (isPendingPassThrough(transition)) { mPendingRemotePassthrough.onConsumed(aborted); mPendingRemotePassthrough.mRemoteHandler.onTransitionConsumed(transition, aborted, finishT); mPendingRemotePassthrough = null; ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "onTransitionConsumed for passThrough transition"); } } // TODO: handle transition consumed for active remote handler // TODO: handle transition consumed for active remote handler Loading @@ -495,6 +523,10 @@ class SplitScreenTransitions { mPendingResize.onFinished(wct, mFinishTransaction); mPendingResize.onFinished(wct, mFinishTransaction); mPendingResize = null; mPendingResize = null; ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "onFinish for resize transition"); ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "onFinish for resize transition"); } else if (isPendingPassThrough(mAnimatingTransition)) { mPendingRemotePassthrough.onFinished(wct, mFinishTransaction); mPendingRemotePassthrough = null; ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "onFinish for passThrough transition"); } } mActiveRemoteHandler = null; mActiveRemoteHandler = null; Loading libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +12 −1 Original line number Original line Diff line number Diff line Loading @@ -2710,7 +2710,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, @Nullable TransitionRequestInfo request) { @Nullable TransitionRequestInfo request) { final ActivityManager.RunningTaskInfo triggerTask = request.getTriggerTask(); final ActivityManager.RunningTaskInfo triggerTask = request.getTriggerTask(); if (triggerTask == null) { if (triggerTask == null) { if (isSplitScreenVisible()) { if (isSplitActive()) { ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "handleRequest: transition=%d display rotation", ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "handleRequest: transition=%d display rotation", request.getDebugId()); request.getDebugId()); // Check if the display is rotating. // Check if the display is rotating. Loading @@ -2720,6 +2720,10 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, && displayChange.getStartRotation() != displayChange.getEndRotation()) { && displayChange.getStartRotation() != displayChange.getEndRotation()) { mSplitLayout.setFreezeDividerWindow(true); mSplitLayout.setFreezeDividerWindow(true); } } if (request.getRemoteTransition() != null) { mSplitTransitions.setRemotePassThroughTransition(transition, request.getRemoteTransition()); } // Still want to monitor everything while in split-screen, so return non-null. // Still want to monitor everything while in split-screen, so return non-null. return new WindowContainerTransaction(); return new WindowContainerTransaction(); } else { } else { Loading Loading @@ -3046,6 +3050,13 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, notifySplitAnimationFinished(); notifySplitAnimationFinished(); return true; return true; } } } else if (mSplitTransitions.isPendingPassThrough(transition)) { ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "startAnimation: passThrough transition=%d", info.getDebugId()); mSplitTransitions.mPendingRemotePassthrough.mRemoteHandler.startAnimation(transition, info, startTransaction, finishTransaction, finishCallback); notifySplitAnimationFinished(); return true; } } return startPendingAnimation(transition, info, startTransaction, finishTransaction, return startPendingAnimation(transition, info, startTransaction, finishTransaction, Loading libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java +3 −0 Original line number Original line Diff line number Diff line Loading @@ -190,6 +190,9 @@ public class Transitions implements RemoteCallable<Transitions>, // TRANSIT_FIRST_CUSTOM + 17 // TRANSIT_FIRST_CUSTOM + 17 TaskFragmentOrganizer.TASK_FRAGMENT_TRANSIT_DRAG_RESIZE; TaskFragmentOrganizer.TASK_FRAGMENT_TRANSIT_DRAG_RESIZE; /** Remote Transition that split accepts but ultimately needs to be animated by the remote. */ public static final int TRANSIT_SPLIT_PASSTHROUGH = TRANSIT_FIRST_CUSTOM + 18; /** Transition type for desktop mode transitions. */ /** Transition type for desktop mode transitions. */ public static final int TRANSIT_DESKTOP_MODE_TYPES = public static final int TRANSIT_DESKTOP_MODE_TYPES = WindowManager.TRANSIT_FIRST_CUSTOM + 100; WindowManager.TRANSIT_FIRST_CUSTOM + 100; Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java +28 −0 Original line number Original line Diff line number Diff line Loading @@ -51,8 +51,10 @@ import android.annotation.NonNull; import android.app.ActivityManager; import android.app.ActivityManager; import android.os.Handler; import android.os.Handler; import android.os.IBinder; import android.os.IBinder; import android.os.RemoteException; import android.view.SurfaceControl; import android.view.SurfaceControl; import android.view.SurfaceSession; import android.view.SurfaceSession; import android.window.IRemoteTransition; import android.window.RemoteTransition; import android.window.RemoteTransition; import android.window.TransitionInfo; import android.window.TransitionInfo; import android.window.TransitionRequestInfo; import android.window.TransitionRequestInfo; Loading Loading @@ -326,6 +328,32 @@ public class SplitTransitionTests extends ShellTestCase { assertFalse(mStageCoordinator.isSplitScreenVisible()); assertFalse(mStageCoordinator.isSplitScreenVisible()); } } @Test @UiThreadTest public void testRemotePassThroughInvoked() throws RemoteException { RemoteTransition remoteWrapper = mock(RemoteTransition.class); IRemoteTransition remoteTransition = mock(IRemoteTransition.class); IBinder remoteBinder = mock(IBinder.class); doReturn(remoteBinder).when(remoteTransition).asBinder(); doReturn(remoteTransition).when(remoteWrapper).getRemoteTransition(); TransitionRequestInfo request = new TransitionRequestInfo(TRANSIT_CHANGE, null, remoteWrapper); IBinder transition = mock(IBinder.class); mMainStage.activate(new WindowContainerTransaction(), false); mStageCoordinator.handleRequest(transition, request); TransitionInfo info = new TransitionInfoBuilder(TRANSIT_CHANGE, 0) .build(); boolean accepted = mStageCoordinator.startAnimation(transition, info, mock(SurfaceControl.Transaction.class), mock(SurfaceControl.Transaction.class), mock(Transitions.TransitionFinishCallback.class)); assertTrue(accepted); verify(remoteTransition, times(1)).startAnimation(any(), any(), any(), any()); } @Test @Test @UiThreadTest @UiThreadTest public void testEnterRecentsAndRestore() { public void testEnterRecentsAndRestore() { Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java +32 −0 Original line number Original line Diff line number Diff line Loading @@ -68,6 +68,7 @@ class SplitScreenTransitions { DismissSession mPendingDismiss = null; DismissSession mPendingDismiss = null; EnterSession mPendingEnter = null; EnterSession mPendingEnter = null; TransitSession mPendingResize = null; TransitSession mPendingResize = null; TransitSession mPendingRemotePassthrough = null; private IBinder mAnimatingTransition = null; private IBinder mAnimatingTransition = null; private OneShotRemoteHandler mActiveRemoteHandler = null; private OneShotRemoteHandler mActiveRemoteHandler = null; Loading Loading @@ -320,6 +321,11 @@ class SplitScreenTransitions { return mPendingResize != null && mPendingResize.mTransition == transition; return mPendingResize != null && mPendingResize.mTransition == transition; } } boolean isPendingPassThrough(IBinder transition) { return mPendingRemotePassthrough != null && mPendingRemotePassthrough.mTransition == transition; } @Nullable @Nullable private TransitSession getPendingTransition(IBinder transition) { private TransitSession getPendingTransition(IBinder transition) { if (isPendingEnter(transition)) { if (isPendingEnter(transition)) { Loading @@ -331,6 +337,9 @@ class SplitScreenTransitions { } else if (isPendingResize(transition)) { } else if (isPendingResize(transition)) { ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "\tresolved resize transition"); ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "\tresolved resize transition"); return mPendingResize; return mPendingResize; } else if (isPendingPassThrough(transition)) { ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "\tresolved passThrough transition"); return mPendingRemotePassthrough; } } return null; return null; } } Loading Loading @@ -378,6 +387,19 @@ class SplitScreenTransitions { extraTransitType, resizeAnim); extraTransitType, resizeAnim); } } /** Sets a transition to enter split. */ void setRemotePassThroughTransition(@NonNull IBinder transition, @Nullable RemoteTransition remoteTransition) { mPendingRemotePassthrough = new TransitSession( transition, null, null, remoteTransition, Transitions.TRANSIT_SPLIT_PASSTHROUGH); ProtoLog.v(WM_SHELL_TRANSITIONS, " splitTransition " + " deduced remote passthrough split screen"); ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "setRemotePassThrough: transitType=%d remote=%s", Transitions.TRANSIT_SPLIT_PASSTHROUGH, remoteTransition); } /** Starts a transition to dismiss split. */ /** Starts a transition to dismiss split. */ IBinder startDismissTransition(WindowContainerTransaction wct, IBinder startDismissTransition(WindowContainerTransaction wct, Transitions.TransitionHandler handler, @SplitScreen.StageType int dismissTop, Transitions.TransitionHandler handler, @SplitScreen.StageType int dismissTop, Loading Loading @@ -474,6 +496,12 @@ class SplitScreenTransitions { mPendingResize.onConsumed(aborted); mPendingResize.onConsumed(aborted); mPendingResize = null; mPendingResize = null; ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "onTransitionConsumed for resize transition"); ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "onTransitionConsumed for resize transition"); } else if (isPendingPassThrough(transition)) { mPendingRemotePassthrough.onConsumed(aborted); mPendingRemotePassthrough.mRemoteHandler.onTransitionConsumed(transition, aborted, finishT); mPendingRemotePassthrough = null; ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "onTransitionConsumed for passThrough transition"); } } // TODO: handle transition consumed for active remote handler // TODO: handle transition consumed for active remote handler Loading @@ -495,6 +523,10 @@ class SplitScreenTransitions { mPendingResize.onFinished(wct, mFinishTransaction); mPendingResize.onFinished(wct, mFinishTransaction); mPendingResize = null; mPendingResize = null; ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "onFinish for resize transition"); ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "onFinish for resize transition"); } else if (isPendingPassThrough(mAnimatingTransition)) { mPendingRemotePassthrough.onFinished(wct, mFinishTransaction); mPendingRemotePassthrough = null; ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "onFinish for passThrough transition"); } } mActiveRemoteHandler = null; mActiveRemoteHandler = null; Loading
libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +12 −1 Original line number Original line Diff line number Diff line Loading @@ -2710,7 +2710,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, @Nullable TransitionRequestInfo request) { @Nullable TransitionRequestInfo request) { final ActivityManager.RunningTaskInfo triggerTask = request.getTriggerTask(); final ActivityManager.RunningTaskInfo triggerTask = request.getTriggerTask(); if (triggerTask == null) { if (triggerTask == null) { if (isSplitScreenVisible()) { if (isSplitActive()) { ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "handleRequest: transition=%d display rotation", ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "handleRequest: transition=%d display rotation", request.getDebugId()); request.getDebugId()); // Check if the display is rotating. // Check if the display is rotating. Loading @@ -2720,6 +2720,10 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, && displayChange.getStartRotation() != displayChange.getEndRotation()) { && displayChange.getStartRotation() != displayChange.getEndRotation()) { mSplitLayout.setFreezeDividerWindow(true); mSplitLayout.setFreezeDividerWindow(true); } } if (request.getRemoteTransition() != null) { mSplitTransitions.setRemotePassThroughTransition(transition, request.getRemoteTransition()); } // Still want to monitor everything while in split-screen, so return non-null. // Still want to monitor everything while in split-screen, so return non-null. return new WindowContainerTransaction(); return new WindowContainerTransaction(); } else { } else { Loading Loading @@ -3046,6 +3050,13 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, notifySplitAnimationFinished(); notifySplitAnimationFinished(); return true; return true; } } } else if (mSplitTransitions.isPendingPassThrough(transition)) { ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "startAnimation: passThrough transition=%d", info.getDebugId()); mSplitTransitions.mPendingRemotePassthrough.mRemoteHandler.startAnimation(transition, info, startTransaction, finishTransaction, finishCallback); notifySplitAnimationFinished(); return true; } } return startPendingAnimation(transition, info, startTransaction, finishTransaction, return startPendingAnimation(transition, info, startTransaction, finishTransaction, Loading
libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java +3 −0 Original line number Original line Diff line number Diff line Loading @@ -190,6 +190,9 @@ public class Transitions implements RemoteCallable<Transitions>, // TRANSIT_FIRST_CUSTOM + 17 // TRANSIT_FIRST_CUSTOM + 17 TaskFragmentOrganizer.TASK_FRAGMENT_TRANSIT_DRAG_RESIZE; TaskFragmentOrganizer.TASK_FRAGMENT_TRANSIT_DRAG_RESIZE; /** Remote Transition that split accepts but ultimately needs to be animated by the remote. */ public static final int TRANSIT_SPLIT_PASSTHROUGH = TRANSIT_FIRST_CUSTOM + 18; /** Transition type for desktop mode transitions. */ /** Transition type for desktop mode transitions. */ public static final int TRANSIT_DESKTOP_MODE_TYPES = public static final int TRANSIT_DESKTOP_MODE_TYPES = WindowManager.TRANSIT_FIRST_CUSTOM + 100; WindowManager.TRANSIT_FIRST_CUSTOM + 100; Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java +28 −0 Original line number Original line Diff line number Diff line Loading @@ -51,8 +51,10 @@ import android.annotation.NonNull; import android.app.ActivityManager; import android.app.ActivityManager; import android.os.Handler; import android.os.Handler; import android.os.IBinder; import android.os.IBinder; import android.os.RemoteException; import android.view.SurfaceControl; import android.view.SurfaceControl; import android.view.SurfaceSession; import android.view.SurfaceSession; import android.window.IRemoteTransition; import android.window.RemoteTransition; import android.window.RemoteTransition; import android.window.TransitionInfo; import android.window.TransitionInfo; import android.window.TransitionRequestInfo; import android.window.TransitionRequestInfo; Loading Loading @@ -326,6 +328,32 @@ public class SplitTransitionTests extends ShellTestCase { assertFalse(mStageCoordinator.isSplitScreenVisible()); assertFalse(mStageCoordinator.isSplitScreenVisible()); } } @Test @UiThreadTest public void testRemotePassThroughInvoked() throws RemoteException { RemoteTransition remoteWrapper = mock(RemoteTransition.class); IRemoteTransition remoteTransition = mock(IRemoteTransition.class); IBinder remoteBinder = mock(IBinder.class); doReturn(remoteBinder).when(remoteTransition).asBinder(); doReturn(remoteTransition).when(remoteWrapper).getRemoteTransition(); TransitionRequestInfo request = new TransitionRequestInfo(TRANSIT_CHANGE, null, remoteWrapper); IBinder transition = mock(IBinder.class); mMainStage.activate(new WindowContainerTransaction(), false); mStageCoordinator.handleRequest(transition, request); TransitionInfo info = new TransitionInfoBuilder(TRANSIT_CHANGE, 0) .build(); boolean accepted = mStageCoordinator.startAnimation(transition, info, mock(SurfaceControl.Transaction.class), mock(SurfaceControl.Transaction.class), mock(Transitions.TransitionFinishCallback.class)); assertTrue(accepted); verify(remoteTransition, times(1)).startAnimation(any(), any(), any(), any()); } @Test @Test @UiThreadTest @UiThreadTest public void testEnterRecentsAndRestore() { public void testEnterRecentsAndRestore() { Loading