Ensure that windows are drawn before starting transition into PiP.
- Building upon ag/2125930, we ensure that all windows are drawn before
starting the enter PiP animation.
Bug: 37420370
Test: bit FrameworksServicesTests:com.android.server.wm.BoundsAnimationControllerTests
Test: android.server.cts.ActivityManagerPinnedStackTests
Change-Id: I73fb71681f62bbc684efedbd3d40c3e1a670db46
diff --git a/services/core/java/com/android/server/wm/BoundsAnimationController.java b/services/core/java/com/android/server/wm/BoundsAnimationController.java
index 7f3c89c..410efcd 100644
--- a/services/core/java/com/android/server/wm/BoundsAnimationController.java
+++ b/services/core/java/com/android/server/wm/BoundsAnimationController.java
@@ -139,8 +139,14 @@
private final boolean mSkipAnimationStart;
// True if this animation was canceled by the user, not as a part of a replacing animation
private boolean mSkipAnimationEnd;
+
+ // True if the animation target is animating from the fullscreen. Only one of
+ // {@link mMoveToFullscreen} or {@link mMoveFromFullscreen} can be true at any time in the
+ // animation.
+ private boolean mMoveFromFullscreen;
// True if the animation target should be moved to the fullscreen stack at the end of this
- // animation
+ // animation. Only one of {@link mMoveToFullscreen} or {@link mMoveFromFullscreen} can be
+ // true at any time in the animation.
private boolean mMoveToFullscreen;
// Whether to schedule PiP mode changes on animation start/end
@@ -151,15 +157,21 @@
private final int mFrozenTaskWidth;
private final int mFrozenTaskHeight;
+ // Timeout callback to ensure we continue the animation if waiting for resuming or app
+ // windows drawn fails
+ private final Runnable mResumeRunnable = () -> resume();
+
BoundsAnimator(BoundsAnimationTarget target, Rect from, Rect to,
@SchedulePipModeChangedState int schedulePipModeChangedState,
- boolean moveToFullscreen, boolean replacingExistingAnimation) {
+ boolean moveFromFullscreen, boolean moveToFullscreen,
+ boolean replacingExistingAnimation) {
super();
mTarget = target;
mFrom.set(from);
mTo.set(to);
mSkipAnimationStart = replacingExistingAnimation;
mSchedulePipModeChangedState = schedulePipModeChangedState;
+ mMoveFromFullscreen = moveFromFullscreen;
mMoveToFullscreen = moveToFullscreen;
addUpdateListener(this);
addListener(this);
@@ -177,13 +189,6 @@
}
}
- final Runnable mResumeRunnable = new Runnable() {
- @Override
- public void run() {
- resume();
- }
- };
-
@Override
public void onAnimationStart(Animator animation) {
if (DEBUG) Slog.d(TAG, "onAnimationStart: mTarget=" + mTarget
@@ -199,6 +204,12 @@
if (!mSkipAnimationStart) {
mTarget.onAnimationStart(mSchedulePipModeChangedState ==
SCHEDULE_PIP_MODE_CHANGED_ON_START);
+
+ // When starting an animation from fullscreen, pause here and wait for the
+ // windows-drawn signal before we start the rest of the transition down into PiP.
+ if (mMoveFromFullscreen) {
+ pause();
+ }
}
// Immediately update the task bounds if they have to become larger, but preserve
@@ -213,13 +224,20 @@
// correct logic to make this resize seamless.
if (mMoveToFullscreen) {
pause();
- mHandler.postDelayed(mResumeRunnable, WAIT_FOR_DRAW_TIMEOUT_MS);
}
}
}
@Override
+ public void pause() {
+ if (DEBUG) Slog.d(TAG, "pause: waiting for windows drawn");
+ super.pause();
+ mHandler.postDelayed(mResumeRunnable, WAIT_FOR_DRAW_TIMEOUT_MS);
+ }
+
+ @Override
public void resume() {
+ if (DEBUG) Slog.d(TAG, "resume:");
mHandler.removeCallbacks(mResumeRunnable);
super.resume();
}
@@ -336,15 +354,15 @@
public void animateBounds(final BoundsAnimationTarget target, Rect from, Rect to,
int animationDuration, @SchedulePipModeChangedState int schedulePipModeChangedState,
- boolean moveToFullscreen) {
+ boolean moveFromFullscreen, boolean moveToFullscreen) {
animateBoundsImpl(target, from, to, animationDuration, schedulePipModeChangedState,
- moveToFullscreen);
+ moveFromFullscreen, moveToFullscreen);
}
@VisibleForTesting
BoundsAnimator animateBoundsImpl(final BoundsAnimationTarget target, Rect from, Rect to,
int animationDuration, @SchedulePipModeChangedState int schedulePipModeChangedState,
- boolean moveToFullscreen) {
+ boolean moveFromFullscreen, boolean moveToFullscreen) {
final BoundsAnimator existing = mRunningAnimations.get(target);
final boolean replacing = existing != null;
@@ -387,7 +405,7 @@
existing.cancel();
}
final BoundsAnimator animator = new BoundsAnimator(target, from, to,
- schedulePipModeChangedState, moveToFullscreen, replacing);
+ schedulePipModeChangedState, moveFromFullscreen, moveToFullscreen, replacing);
mRunningAnimations.put(target, animator);
animator.setFloatValues(0f, 1f);
animator.setDuration((animationDuration != -1 ? animationDuration
@@ -397,14 +415,19 @@
return animator;
}
+ public Handler getHandler() {
+ return mHandler;
+ }
+
+ public void onAllWindowsDrawn() {
+ if (DEBUG) Slog.d(TAG, "onAllWindowsDrawn:");
+ mHandler.post(this::resume);
+ }
+
private void resume() {
for (int i = 0; i < mRunningAnimations.size(); i++) {
final BoundsAnimator b = mRunningAnimations.valueAt(i);
b.resume();
}
}
-
- public void onAllWindowsDrawn() {
- mHandler.post(this::resume);
- }
}