diff options
3 files changed, 73 insertions, 37 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java index cf2734c375f2..81e49f884503 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java @@ -183,7 +183,7 @@ public class PipAnimationController { return mCurrentAnimator; } - PipTransitionAnimator getCurrentAnimator() { + public PipTransitionAnimator getCurrentAnimator() { return mCurrentAnimator; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java index 1155ea174ed1..f747b5e00759 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java @@ -127,7 +127,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, private final PipBoundsAlgorithm mPipBoundsAlgorithm; private final @NonNull PipMenuController mPipMenuController; private final PipAnimationController mPipAnimationController; - private final PipTransitionController mPipTransitionController; + protected final PipTransitionController mPipTransitionController; protected final PipParamsChangedForwarder mPipParamsChangedForwarder; private final PipUiEventLogger mPipUiEventLoggerLogger; private final int mEnterAnimationDuration; @@ -196,6 +196,26 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, } }; + @VisibleForTesting + final PipTransitionController.PipTransitionCallback mPipTransitionCallback = + new PipTransitionController.PipTransitionCallback() { + @Override + public void onPipTransitionStarted(int direction, Rect pipBounds) {} + + @Override + public void onPipTransitionFinished(int direction) { + // Apply the deferred RunningTaskInfo if applicable after all proper callbacks + // are sent. + if (direction == TRANSITION_DIRECTION_TO_PIP && mDeferredTaskInfo != null) { + onTaskInfoChanged(mDeferredTaskInfo); + mDeferredTaskInfo = null; + } + } + + @Override + public void onPipTransitionCanceled(int direction) {} + }; + private final PipAnimationController.PipTransactionHandler mPipTransactionHandler = new PipAnimationController.PipTransactionHandler() { @Override @@ -216,7 +236,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, private ActivityManager.RunningTaskInfo mDeferredTaskInfo; private WindowContainerToken mToken; private SurfaceControl mLeash; - private PipTransitionState mPipTransitionState; + protected PipTransitionState mPipTransitionState; private @PipAnimationController.AnimationType int mOneShotAnimationType = ANIM_TYPE_BOUNDS; private long mLastOneShotAlphaAnimationTime; private PipSurfaceTransactionHelper.SurfaceControlTransactionFactory @@ -296,6 +316,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, mTaskOrganizer.addFocusListener(this); mPipTransitionController.setPipOrganizer(this); displayController.addDisplayWindowListener(this); + pipTransitionController.registerPipTransitionCallback(mPipTransitionCallback); } public PipTransitionController getTransitionController() { @@ -773,11 +794,6 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, mPipTransitionState.setTransitionState(PipTransitionState.ENTERED_PIP); } mPipTransitionController.sendOnPipTransitionFinished(direction); - // Apply the deferred RunningTaskInfo if applicable after all proper callbacks are sent. - if (direction == TRANSITION_DIRECTION_TO_PIP && mDeferredTaskInfo != null) { - onTaskInfoChanged(mDeferredTaskInfo); - mDeferredTaskInfo = null; - } } private void sendOnPipTransitionCancelled( diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java index 857f578fd8ed..579638d28311 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java @@ -21,13 +21,13 @@ import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTI import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyFloat; import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; -import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import android.app.ActivityManager; @@ -70,7 +70,7 @@ import java.util.Optional; @RunWith(AndroidTestingRunner.class) @TestableLooper.RunWithLooper public class PipTaskOrganizerTest extends ShellTestCase { - private PipTaskOrganizer mSpiedPipTaskOrganizer; + private PipTaskOrganizer mPipTaskOrganizer; @Mock private DisplayController mMockDisplayController; @Mock private SyncTransactionQueue mMockSyncTransactionQueue; @@ -100,14 +100,15 @@ public class PipTaskOrganizerTest extends ShellTestCase { mPipBoundsAlgorithm = new PipBoundsAlgorithm(mContext, mPipBoundsState, new PipSnapAlgorithm()); mMainExecutor = new TestShellExecutor(); - mSpiedPipTaskOrganizer = spy(new PipTaskOrganizer(mContext, + mPipTaskOrganizer = new PipTaskOrganizer(mContext, mMockSyncTransactionQueue, mPipTransitionState, mPipBoundsState, mPipBoundsAlgorithm, mMockPhonePipMenuController, mMockPipAnimationController, mMockPipSurfaceTransactionHelper, mMockPipTransitionController, mMockPipParamsChangedForwarder, mMockOptionalSplitScreen, mMockDisplayController, - mMockPipUiEventLogger, mMockShellTaskOrganizer, mMainExecutor)); + mMockPipUiEventLogger, mMockShellTaskOrganizer, mMainExecutor); mMainExecutor.flushAll(); preparePipTaskOrg(); + preparePipSurfaceTransactionHelper(); } @Test @@ -124,14 +125,14 @@ public class PipTaskOrganizerTest extends ShellTestCase { public void startSwipePipToHome_updatesAspectRatio() { final Rational aspectRatio = new Rational(2, 1); - mSpiedPipTaskOrganizer.startSwipePipToHome(mComponent1, null, createPipParams(aspectRatio)); + mPipTaskOrganizer.startSwipePipToHome(mComponent1, null, createPipParams(aspectRatio)); assertEquals(aspectRatio.floatValue(), mPipBoundsState.getAspectRatio(), 0.01f); } @Test public void startSwipePipToHome_updatesLastPipComponentName() { - mSpiedPipTaskOrganizer.startSwipePipToHome(mComponent1, null, createPipParams(null)); + mPipTaskOrganizer.startSwipePipToHome(mComponent1, null, createPipParams(null)); assertEquals(mComponent1, mPipBoundsState.getLastPipComponentName()); } @@ -140,7 +141,7 @@ public class PipTaskOrganizerTest extends ShellTestCase { public void startSwipePipToHome_updatesOverrideMinSize() { final Size minSize = new Size(400, 320); - mSpiedPipTaskOrganizer.startSwipePipToHome(mComponent1, createActivityInfo(minSize), + mPipTaskOrganizer.startSwipePipToHome(mComponent1, createActivityInfo(minSize), createPipParams(null)); assertEquals(minSize, mPipBoundsState.getOverrideMinSize()); @@ -150,7 +151,7 @@ public class PipTaskOrganizerTest extends ShellTestCase { public void onTaskAppeared_updatesAspectRatio() { final Rational aspectRatio = new Rational(2, 1); - mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1, + mPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1, createPipParams(aspectRatio)), mock(SurfaceControl.class)); assertEquals(aspectRatio.floatValue(), mPipBoundsState.getAspectRatio(), 0.01f); @@ -158,7 +159,7 @@ public class PipTaskOrganizerTest extends ShellTestCase { @Test public void onTaskAppeared_updatesLastPipComponentName() { - mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1, createPipParams(null)), + mPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1, createPipParams(null)), mock(SurfaceControl.class)); assertEquals(mComponent1, mPipBoundsState.getLastPipComponentName()); @@ -168,7 +169,7 @@ public class PipTaskOrganizerTest extends ShellTestCase { public void onTaskAppeared_updatesOverrideMinSize() { final Size minSize = new Size(400, 320); - mSpiedPipTaskOrganizer.onTaskAppeared( + mPipTaskOrganizer.onTaskAppeared( createTaskInfo(mComponent1, createPipParams(null), minSize), mock(SurfaceControl.class)); @@ -179,16 +180,16 @@ public class PipTaskOrganizerTest extends ShellTestCase { public void onTaskInfoChanged_notInPip_deferUpdatesAspectRatio() { final Rational startAspectRatio = new Rational(2, 1); final Rational newAspectRatio = new Rational(1, 2); - mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1, + mPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1, createPipParams(startAspectRatio)), mock(SurfaceControl.class)); // It is in entering transition, should defer onTaskInfoChanged callback in this case. - mSpiedPipTaskOrganizer.onTaskInfoChanged(createTaskInfo(mComponent1, + mPipTaskOrganizer.onTaskInfoChanged(createTaskInfo(mComponent1, createPipParams(newAspectRatio))); verify(mMockPipParamsChangedForwarder, never()).notifyAspectRatioChanged(anyFloat()); // Once the entering transition finishes, the new aspect ratio applies in a deferred manner - mSpiedPipTaskOrganizer.sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP); + sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP); verify(mMockPipParamsChangedForwarder) .notifyAspectRatioChanged(newAspectRatio.floatValue()); } @@ -197,11 +198,11 @@ public class PipTaskOrganizerTest extends ShellTestCase { public void onTaskInfoChanged_inPip_updatesAspectRatioIfChanged() { final Rational startAspectRatio = new Rational(2, 1); final Rational newAspectRatio = new Rational(1, 2); - mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1, + mPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1, createPipParams(startAspectRatio)), mock(SurfaceControl.class)); - mSpiedPipTaskOrganizer.sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP); + sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP); - mSpiedPipTaskOrganizer.onTaskInfoChanged(createTaskInfo(mComponent1, + mPipTaskOrganizer.onTaskInfoChanged(createTaskInfo(mComponent1, createPipParams(newAspectRatio))); verify(mMockPipParamsChangedForwarder) @@ -210,11 +211,11 @@ public class PipTaskOrganizerTest extends ShellTestCase { @Test public void onTaskInfoChanged_inPip_updatesLastPipComponentName() { - mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1, + mPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1, createPipParams(null)), mock(SurfaceControl.class)); - mSpiedPipTaskOrganizer.sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP); + sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP); - mSpiedPipTaskOrganizer.onTaskInfoChanged(createTaskInfo(mComponent2, + mPipTaskOrganizer.onTaskInfoChanged(createTaskInfo(mComponent2, createPipParams(null))); assertEquals(mComponent2, mPipBoundsState.getLastPipComponentName()); @@ -222,12 +223,12 @@ public class PipTaskOrganizerTest extends ShellTestCase { @Test public void onTaskInfoChanged_inPip_updatesOverrideMinSize() { - mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1, + mPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1, createPipParams(null)), mock(SurfaceControl.class)); - mSpiedPipTaskOrganizer.sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP); + sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP); final Size minSize = new Size(400, 320); - mSpiedPipTaskOrganizer.onTaskInfoChanged(createTaskInfo(mComponent2, + mPipTaskOrganizer.onTaskInfoChanged(createTaskInfo(mComponent2, createPipParams(null), minSize)); assertEquals(minSize, mPipBoundsState.getOverrideMinSize()); @@ -235,23 +236,42 @@ public class PipTaskOrganizerTest extends ShellTestCase { @Test public void onTaskVanished_clearsPipBounds() { - mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1, + mPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1, createPipParams(null)), mock(SurfaceControl.class)); mPipBoundsState.setBounds(new Rect(100, 100, 200, 150)); - mSpiedPipTaskOrganizer.onTaskVanished(createTaskInfo(mComponent1, createPipParams(null))); + mPipTaskOrganizer.onTaskVanished(createTaskInfo(mComponent1, createPipParams(null))); assertTrue(mPipBoundsState.getBounds().isEmpty()); } + private void sendOnPipTransitionFinished( + @PipAnimationController.TransitionDirection int direction) { + mPipTaskOrganizer.sendOnPipTransitionFinished(direction); + // PipTransitionController will call back into PipTaskOrganizer. + mPipTaskOrganizer.mPipTransitionCallback.onPipTransitionFinished(direction); + } + private void preparePipTaskOrg() { final DisplayInfo info = new DisplayInfo(); mPipBoundsState.setDisplayLayout(new DisplayLayout(info, mContext.getResources(), true, true)); - mSpiedPipTaskOrganizer.setOneShotAnimationType(PipAnimationController.ANIM_TYPE_ALPHA); - mSpiedPipTaskOrganizer.setSurfaceControlTransactionFactory( + mPipTaskOrganizer.setOneShotAnimationType(PipAnimationController.ANIM_TYPE_ALPHA); + mPipTaskOrganizer.setSurfaceControlTransactionFactory( MockSurfaceControlHelper::createMockSurfaceControlTransaction); - doNothing().when(mSpiedPipTaskOrganizer).enterPipWithAlphaAnimation(any(), anyLong()); - doNothing().when(mSpiedPipTaskOrganizer).scheduleAnimateResizePip(any(), anyInt(), any()); + } + + private void preparePipSurfaceTransactionHelper() { + doReturn(mMockPipSurfaceTransactionHelper).when(mMockPipSurfaceTransactionHelper) + .crop(any(), any(), any()); + doReturn(mMockPipSurfaceTransactionHelper).when(mMockPipSurfaceTransactionHelper) + .resetScale(any(), any(), any()); + doReturn(mMockPipSurfaceTransactionHelper).when(mMockPipSurfaceTransactionHelper) + .round(any(), any(), anyBoolean()); + doReturn(mMockPipSurfaceTransactionHelper).when(mMockPipSurfaceTransactionHelper) + .scale(any(), any(), any(), any(), anyFloat()); + doReturn(mMockPipSurfaceTransactionHelper).when(mMockPipSurfaceTransactionHelper) + .alpha(any(), any(), anyFloat()); + doNothing().when(mMockPipSurfaceTransactionHelper).onDensityOrFontScaleChanged(any()); } private static ActivityManager.RunningTaskInfo createTaskInfo( |