summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Ikram Gabiyev <gabiyev@google.com> 2025-03-06 11:59:01 -0800
committer Android (Google) Code Review <android-gerrit@google.com> 2025-03-06 11:59:01 -0800
commite65271a8db9317943bac6b00c48cd420b7ece282 (patch)
treeb490ce6c6a3ea9bc7ef6527290511506db96b6a9
parent7c5321f09313c28fe7ca04d3b6c46579612f12bb (diff)
parentff56fe9985c255cf78977846ef98ce814e5e9768 (diff)
Merge "[PiP2] End overlay animation if user interacts" into main
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipScheduler.java45
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip2/phone/PipSchedulerTest.java26
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);
}