Loading libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipScheduler.java +39 −6 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.app.PictureInPictureParams; import android.content.Context; import android.graphics.Matrix; import android.graphics.Rect; import android.os.Bundle; import android.os.SystemProperties; import android.view.SurfaceControl; import android.window.WindowContainerToken; Loading Loading @@ -47,7 +48,7 @@ import java.util.function.Supplier; /** * Scheduler for Shell initiated PiP transitions and animations. */ public class PipScheduler { public class PipScheduler implements PipTransitionState.PipTransitionStateChangedListener { private static final String TAG = PipScheduler.class.getSimpleName(); /** Loading @@ -71,6 +72,7 @@ public class PipScheduler { private final PipSurfaceTransactionHelper mPipSurfaceTransactionHelper; @Nullable private Runnable mUpdateMovementBoundsRunnable; @Nullable private PipAlphaAnimator mOverlayFadeoutAnimator; private PipAlphaAnimatorSupplier mPipAlphaAnimatorSupplier; private Supplier<PictureInPictureParams> mPipParamsSupplier; Loading @@ -85,6 +87,7 @@ public class PipScheduler { mPipBoundsState = pipBoundsState; mMainExecutor = mainExecutor; mPipTransitionState = pipTransitionState; mPipTransitionState.addPipTransitionStateChangedListener(this); mPipDesktopState = pipDesktopState; mSplitScreenControllerOptional = splitScreenControllerOptional; Loading Loading @@ -238,12 +241,16 @@ public class PipScheduler { void startOverlayFadeoutAnimation(@NonNull SurfaceControl overlayLeash, boolean withStartDelay, @NonNull Runnable onAnimationEnd) { PipAlphaAnimator animator = mPipAlphaAnimatorSupplier.get(mContext, overlayLeash, mOverlayFadeoutAnimator = mPipAlphaAnimatorSupplier.get(mContext, overlayLeash, null /* startTx */, null /* finishTx */, PipAlphaAnimator.FADE_OUT); animator.setDuration(CONTENT_OVERLAY_FADE_OUT_DURATION_MS); animator.setStartDelay(withStartDelay ? EXTRA_CONTENT_OVERLAY_FADE_OUT_DELAY_MS : 0); animator.setAnimationEndCallback(onAnimationEnd); animator.start(); mOverlayFadeoutAnimator.setDuration(CONTENT_OVERLAY_FADE_OUT_DURATION_MS); mOverlayFadeoutAnimator.setStartDelay(withStartDelay ? EXTRA_CONTENT_OVERLAY_FADE_OUT_DELAY_MS : 0); mOverlayFadeoutAnimator.setAnimationEndCallback(() -> { onAnimationEnd.run(); mOverlayFadeoutAnimator = null; }); mOverlayFadeoutAnimator.start(); } void setUpdateMovementBoundsRunnable(@Nullable Runnable updateMovementBoundsRunnable) { Loading Loading @@ -289,6 +296,21 @@ public class PipScheduler { mSurfaceControlTransactionFactory = factory; } @Override public void onPipTransitionStateChanged(@PipTransitionState.TransitionState int oldState, @PipTransitionState.TransitionState int newState, @android.annotation.Nullable Bundle extra) { switch (newState) { case PipTransitionState.EXITING_PIP: case PipTransitionState.SCHEDULED_BOUNDS_CHANGE: if (mOverlayFadeoutAnimator != null && mOverlayFadeoutAnimator.isStarted()) { mOverlayFadeoutAnimator.end(); mOverlayFadeoutAnimator = null; } break; } } @VisibleForTesting interface PipAlphaAnimatorSupplier { PipAlphaAnimator get(@NonNull Context context, Loading @@ -303,6 +325,17 @@ public class PipScheduler { mPipAlphaAnimatorSupplier = supplier; } @VisibleForTesting void setOverlayFadeoutAnimator(@NonNull PipAlphaAnimator animator) { mOverlayFadeoutAnimator = animator; } @VisibleForTesting @Nullable PipAlphaAnimator getOverlayFadeoutAnimator() { return mOverlayFadeoutAnimator; } void setPipParamsSupplier(@NonNull Supplier<PictureInPictureParams> pipParamsSupplier) { mPipParamsSupplier = pipParamsSupplier; } Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip2/phone/PipSchedulerTest.java +26 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.wm.shell.pip2.phone; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; Loading Loading @@ -86,6 +87,7 @@ public class PipSchedulerTest { @Mock private SurfaceControl.Transaction mMockTransaction; @Mock private PipAlphaAnimator mMockAlphaAnimator; @Mock private SplitScreenController mMockSplitScreenController; @Mock private SurfaceControl mMockLeash; @Captor private ArgumentCaptor<Runnable> mRunnableArgumentCaptor; @Captor private ArgumentCaptor<WindowContainerTransaction> mWctArgumentCaptor; Loading Loading @@ -315,6 +317,30 @@ public class PipSchedulerTest { verify(mMockAlphaAnimator, never()).start(); } @Test public void onPipTransitionStateChanged_exiting_endAnimation() { mPipScheduler.setOverlayFadeoutAnimator(mMockAlphaAnimator); when(mMockAlphaAnimator.isStarted()).thenReturn(true); mPipScheduler.onPipTransitionStateChanged(PipTransitionState.ENTERED_PIP, PipTransitionState.EXITING_PIP, null); verify(mMockAlphaAnimator, times(1)).end(); assertNull("mOverlayFadeoutAnimator should be reset to null", mPipScheduler.getOverlayFadeoutAnimator()); } @Test public void onPipTransitionStateChanged_scheduledBoundsChange_endAnimation() { mPipScheduler.setOverlayFadeoutAnimator(mMockAlphaAnimator); when(mMockAlphaAnimator.isStarted()).thenReturn(true); mPipScheduler.onPipTransitionStateChanged(PipTransitionState.ENTERED_PIP, PipTransitionState.SCHEDULED_BOUNDS_CHANGE, null); verify(mMockAlphaAnimator, times(1)).end(); assertNull("mOverlayFadeoutAnimator should be reset to null", mPipScheduler.getOverlayFadeoutAnimator()); } private void setNullPipTaskToken() { when(mMockPipTransitionState.getPipTaskToken()).thenReturn(null); } Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipScheduler.java +39 −6 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.app.PictureInPictureParams; import android.content.Context; import android.graphics.Matrix; import android.graphics.Rect; import android.os.Bundle; import android.os.SystemProperties; import android.view.SurfaceControl; import android.window.WindowContainerToken; Loading Loading @@ -47,7 +48,7 @@ import java.util.function.Supplier; /** * Scheduler for Shell initiated PiP transitions and animations. */ public class PipScheduler { public class PipScheduler implements PipTransitionState.PipTransitionStateChangedListener { private static final String TAG = PipScheduler.class.getSimpleName(); /** Loading @@ -71,6 +72,7 @@ public class PipScheduler { private final PipSurfaceTransactionHelper mPipSurfaceTransactionHelper; @Nullable private Runnable mUpdateMovementBoundsRunnable; @Nullable private PipAlphaAnimator mOverlayFadeoutAnimator; private PipAlphaAnimatorSupplier mPipAlphaAnimatorSupplier; private Supplier<PictureInPictureParams> mPipParamsSupplier; Loading @@ -85,6 +87,7 @@ public class PipScheduler { mPipBoundsState = pipBoundsState; mMainExecutor = mainExecutor; mPipTransitionState = pipTransitionState; mPipTransitionState.addPipTransitionStateChangedListener(this); mPipDesktopState = pipDesktopState; mSplitScreenControllerOptional = splitScreenControllerOptional; Loading Loading @@ -238,12 +241,16 @@ public class PipScheduler { void startOverlayFadeoutAnimation(@NonNull SurfaceControl overlayLeash, boolean withStartDelay, @NonNull Runnable onAnimationEnd) { PipAlphaAnimator animator = mPipAlphaAnimatorSupplier.get(mContext, overlayLeash, mOverlayFadeoutAnimator = mPipAlphaAnimatorSupplier.get(mContext, overlayLeash, null /* startTx */, null /* finishTx */, PipAlphaAnimator.FADE_OUT); animator.setDuration(CONTENT_OVERLAY_FADE_OUT_DURATION_MS); animator.setStartDelay(withStartDelay ? EXTRA_CONTENT_OVERLAY_FADE_OUT_DELAY_MS : 0); animator.setAnimationEndCallback(onAnimationEnd); animator.start(); mOverlayFadeoutAnimator.setDuration(CONTENT_OVERLAY_FADE_OUT_DURATION_MS); mOverlayFadeoutAnimator.setStartDelay(withStartDelay ? EXTRA_CONTENT_OVERLAY_FADE_OUT_DELAY_MS : 0); mOverlayFadeoutAnimator.setAnimationEndCallback(() -> { onAnimationEnd.run(); mOverlayFadeoutAnimator = null; }); mOverlayFadeoutAnimator.start(); } void setUpdateMovementBoundsRunnable(@Nullable Runnable updateMovementBoundsRunnable) { Loading Loading @@ -289,6 +296,21 @@ public class PipScheduler { mSurfaceControlTransactionFactory = factory; } @Override public void onPipTransitionStateChanged(@PipTransitionState.TransitionState int oldState, @PipTransitionState.TransitionState int newState, @android.annotation.Nullable Bundle extra) { switch (newState) { case PipTransitionState.EXITING_PIP: case PipTransitionState.SCHEDULED_BOUNDS_CHANGE: if (mOverlayFadeoutAnimator != null && mOverlayFadeoutAnimator.isStarted()) { mOverlayFadeoutAnimator.end(); mOverlayFadeoutAnimator = null; } break; } } @VisibleForTesting interface PipAlphaAnimatorSupplier { PipAlphaAnimator get(@NonNull Context context, Loading @@ -303,6 +325,17 @@ public class PipScheduler { mPipAlphaAnimatorSupplier = supplier; } @VisibleForTesting void setOverlayFadeoutAnimator(@NonNull PipAlphaAnimator animator) { mOverlayFadeoutAnimator = animator; } @VisibleForTesting @Nullable PipAlphaAnimator getOverlayFadeoutAnimator() { return mOverlayFadeoutAnimator; } void setPipParamsSupplier(@NonNull Supplier<PictureInPictureParams> pipParamsSupplier) { mPipParamsSupplier = pipParamsSupplier; } Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip2/phone/PipSchedulerTest.java +26 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.wm.shell.pip2.phone; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; Loading Loading @@ -86,6 +87,7 @@ public class PipSchedulerTest { @Mock private SurfaceControl.Transaction mMockTransaction; @Mock private PipAlphaAnimator mMockAlphaAnimator; @Mock private SplitScreenController mMockSplitScreenController; @Mock private SurfaceControl mMockLeash; @Captor private ArgumentCaptor<Runnable> mRunnableArgumentCaptor; @Captor private ArgumentCaptor<WindowContainerTransaction> mWctArgumentCaptor; Loading Loading @@ -315,6 +317,30 @@ public class PipSchedulerTest { verify(mMockAlphaAnimator, never()).start(); } @Test public void onPipTransitionStateChanged_exiting_endAnimation() { mPipScheduler.setOverlayFadeoutAnimator(mMockAlphaAnimator); when(mMockAlphaAnimator.isStarted()).thenReturn(true); mPipScheduler.onPipTransitionStateChanged(PipTransitionState.ENTERED_PIP, PipTransitionState.EXITING_PIP, null); verify(mMockAlphaAnimator, times(1)).end(); assertNull("mOverlayFadeoutAnimator should be reset to null", mPipScheduler.getOverlayFadeoutAnimator()); } @Test public void onPipTransitionStateChanged_scheduledBoundsChange_endAnimation() { mPipScheduler.setOverlayFadeoutAnimator(mMockAlphaAnimator); when(mMockAlphaAnimator.isStarted()).thenReturn(true); mPipScheduler.onPipTransitionStateChanged(PipTransitionState.ENTERED_PIP, PipTransitionState.SCHEDULED_BOUNDS_CHANGE, null); verify(mMockAlphaAnimator, times(1)).end(); assertNull("mOverlayFadeoutAnimator should be reset to null", mPipScheduler.getOverlayFadeoutAnimator()); } private void setNullPipTaskToken() { when(mMockPipTransitionState.getPipTaskToken()).thenReturn(null); } Loading