diff options
| author | 2025-03-06 11:59:01 -0800 | |
|---|---|---|
| committer | 2025-03-06 11:59:01 -0800 | |
| commit | e65271a8db9317943bac6b00c48cd420b7ece282 (patch) | |
| tree | b490ce6c6a3ea9bc7ef6527290511506db96b6a9 | |
| parent | 7c5321f09313c28fe7ca04d3b6c46579612f12bb (diff) | |
| parent | ff56fe9985c255cf78977846ef98ce814e5e9768 (diff) | |
Merge "[PiP2] End overlay animation if user interacts" into main
2 files changed, 65 insertions, 6 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipScheduler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipScheduler.java index 383afcf6f821..f81f330e50c4 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipScheduler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipScheduler.java @@ -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; @@ -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(); /** @@ -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; @@ -85,6 +87,7 @@ public class PipScheduler { mPipBoundsState = pipBoundsState; mMainExecutor = mainExecutor; mPipTransitionState = pipTransitionState; + mPipTransitionState.addPipTransitionStateChangedListener(this); mPipDesktopState = pipDesktopState; mSplitScreenControllerOptional = splitScreenControllerOptional; @@ -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) { @@ -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, @@ -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; } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip2/phone/PipSchedulerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip2/phone/PipSchedulerTest.java index 275e4882a79d..42f65dd71f16 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip2/phone/PipSchedulerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip2/phone/PipSchedulerTest.java @@ -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; @@ -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; @@ -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); } |