PIP: Fix potential stuck state
Fixes an issue where the leave-PIP-animation could be erroneously
canceled and replaced with one that does not leave PIP. This happens
for example when launching a notification that restarts the PIP task
and maximizes it, if that notification is launched from the lockscreen
with a password set.
The task is animating out of PIP, but concurrently, a move animation
is scheduled because the IME that was up for the password is being
dismissed. If the order is such that the leave-PIP-animation is scheduled
first, the task will never be reparented out of PIP.
To fix that, we maintain the to/fromFullscreen flags when recreating the
animation.
Change-Id: I79d6d1907fcb25561d87b746cfb054f230d9d7b9
Fixes: 77334925
Test: Set lockscreen password (not PIN/Pattern). Open PIP app that has a notification from which it can be relaunched. Enter PIP. Lock screen. Relaunch PIP app from lockscreen notification. Verify things look appropriate after unlocking.
Test: atest BoundsAnimationControllerTests
diff --git a/services/core/java/com/android/server/wm/BoundsAnimationController.java b/services/core/java/com/android/server/wm/BoundsAnimationController.java
index 112d93c..b2a12be 100644
--- a/services/core/java/com/android/server/wm/BoundsAnimationController.java
+++ b/services/core/java/com/android/server/wm/BoundsAnimationController.java
@@ -401,12 +401,13 @@
+ " replacing=" + replacing);
if (replacing) {
- if (existing.isAnimatingTo(to)) {
+ if (existing.isAnimatingTo(to) && (!moveToFullscreen || existing.mMoveToFullscreen)
+ && (!moveFromFullscreen || existing.mMoveFromFullscreen)) {
// Just let the current animation complete if it has the same destination as the
- // one we are trying to start.
- if (DEBUG) Slog.d(TAG, "animateBounds: same destination as existing=" + existing
- + " ignoring...");
-
+ // one we are trying to start, and, if moveTo/FromFullscreen was requested, already
+ // has that flag set.
+ if (DEBUG) Slog.d(TAG, "animateBounds: same destination and moveTo/From flags as "
+ + "existing=" + existing + ", ignoring...");
return existing;
}
@@ -434,6 +435,13 @@
}
}
+ // We need to keep the previous moveTo/FromFullscreen flag, unless the new animation
+ // specifies a direction.
+ if (!moveFromFullscreen && !moveToFullscreen) {
+ moveToFullscreen = existing.mMoveToFullscreen;
+ moveFromFullscreen = existing.mMoveFromFullscreen;
+ }
+
// Since we are replacing, we skip both animation start and end callbacks
existing.cancel();
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java
index 6019958..ff631e7 100644
--- a/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java
@@ -545,7 +545,7 @@
.restart(BOUNDS_SMALLER_FLOATING,
false /* expectStartedAndPipModeChangedCallback */)
.end()
- .expectEnded(SCHEDULE_PIP_MODE_CHANGED, !MOVE_TO_FULLSCREEN);
+ .expectEnded(SCHEDULE_PIP_MODE_CHANGED, MOVE_TO_FULLSCREEN);
}
/** !F->!F w/ CANCEL **/