Final fixes for growing recents transition
- Make sure to reposition windows during animations to avoid that
they lag one frame behind.
- Don't put windows that are gone for layout into resizing mode.
- Don't layout windows that are gone for layout, to avoid resizing
the surface but the client won't draw anymore.
Change-Id: I809feffef00f9a086b44504126e03f509eb7f190
Fixes: 27855229
diff --git a/services/core/java/com/android/server/wm/AppWindowAnimator.java b/services/core/java/com/android/server/wm/AppWindowAnimator.java
index aae52e8..abb1bb1 100644
--- a/services/core/java/com/android/server/wm/AppWindowAnimator.java
+++ b/services/core/java/com/android/server/wm/AppWindowAnimator.java
@@ -433,7 +433,7 @@
WindowStateAnimator winAnimator = mAllAppWinAnimators.get(i);
if (DEBUG_VISIBILITY) Slog.v(TAG, "performing show on: " + winAnimator);
winAnimator.performShowLocked();
- isAnimating |= winAnimator.isAnimating();
+ isAnimating |= winAnimator.isAnimationSet();
}
return isAnimating;
}
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 545b9db..9f54b53 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -204,7 +204,7 @@
if (DEBUG_VISIBILITY) {
Slog.v(TAG, "Win " + win + ": isDrawn="
+ win.isDrawnLw()
- + ", isAnimating=" + win.mWinAnimator.isAnimating());
+ + ", isAnimationSet=" + win.mWinAnimator.isAnimationSet());
if (!win.isDrawnLw()) {
Slog.v(TAG, "Not displayed: s=" +
win.mWinAnimator.mSurfaceController
@@ -220,11 +220,11 @@
numInteresting++;
if (win.isDrawnLw()) {
numDrawn++;
- if (!win.mWinAnimator.isAnimating()) {
+ if (!win.mWinAnimator.isAnimationSet()) {
numVisible++;
}
nowGone = false;
- } else if (win.mWinAnimator.isAnimating()) {
+ } else if (win.mWinAnimator.isAnimationSet()) {
nowGone = false;
}
}
@@ -297,7 +297,7 @@
// Return true so that the alpha doesn't get cleared.
if (!win.mAppFreezing
&& (win.mViewVisibility == View.VISIBLE || mAnimatingWithSavedSurface
- || (win.mWinAnimator.isAnimating()
+ || (win.mWinAnimator.isAnimationSet()
&& !service.mAppTransition.isTransitionSet()))
&& !win.mDestroying
&& win.isDrawnLw()) {
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 4f49eed..6925fa5 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -601,7 +601,7 @@
// Anyway we don't need to synchronize position and content updates for these
// windows since they aren't at the base layer and could be moved around anyway.
if (!win.computeDragResizing() && win.mAttrs.type == TYPE_BASE_APPLICATION &&
- !mStack.getBoundsAnimating()) {
+ !mStack.getBoundsAnimating() && !win.isGoneForLayoutLw()) {
win.mResizedWhileNotDragResizing = true;
}
}
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index a289855..467f5b6 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -41,7 +41,6 @@
import android.util.SparseArray;
import android.view.DisplayInfo;
import android.view.Surface;
-import android.view.animation.PathInterpolator;
import android.view.SurfaceControl;
import com.android.internal.policy.DividerSnapAlgorithm;
@@ -503,7 +502,7 @@
final ArrayList<WindowState> windows = activities.get(activityNdx).allAppWindows;
for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
final WindowStateAnimator winAnimator = windows.get(winNdx).mWinAnimator;
- if (winAnimator.isAnimating() || winAnimator.mWin.mAnimatingExit) {
+ if (winAnimator.isAnimationSet() || winAnimator.mWin.mAnimatingExit) {
return true;
}
}
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index e44b0f3..88028be 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -146,7 +146,7 @@
}
boolean isWallpaperTargetAnimating() {
- return mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimating()
+ return mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimationSet()
&& !mWallpaperTarget.mWinAnimator.isDummyAnimation();
}
@@ -516,7 +516,7 @@
if (hasWallpaper && w.isOnScreen() && (mWallpaperTarget == w || w.isDrawFinishedLw())) {
if (DEBUG_WALLPAPER) Slog.v(TAG, "Found wallpaper target: #" + i + "=" + w);
result.setWallpaperTarget(w, i);
- if (w == mWallpaperTarget && w.mWinAnimator.isAnimating()) {
+ if (w == mWallpaperTarget && w.mWinAnimator.isAnimationSet()) {
// The current wallpaper target is animating, so we'll look behind it for
// another possible target and figure out what is going on later.
if (DEBUG_WALLPAPER) Slog.v(TAG,
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index aee8fc9..3af03c7 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -120,7 +120,6 @@
import android.view.WindowManagerPolicy.PointerEventListener;
import android.view.animation.Animation;
import android.view.inputmethod.InputMethodManagerInternal;
-import android.widget.Toast;
import com.android.internal.R;
import com.android.internal.app.IAssistScreenshotReceiver;
@@ -1525,7 +1524,7 @@
if (highestTarget != null) {
if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, mAppTransition + " " + highestTarget
- + " animating=" + highestTarget.mWinAnimator.isAnimating()
+ + " animating=" + highestTarget.mWinAnimator.isAnimationSet()
+ " layer=" + highestTarget.mWinAnimator.mAnimLayer
+ " new layer=" + w.mWinAnimator.mAnimLayer);
@@ -1535,7 +1534,7 @@
mInputMethodTargetWaitingAnim = true;
mInputMethodTarget = highestTarget;
return highestPos + 1;
- } else if (highestTarget.mWinAnimator.isAnimating() &&
+ } else if (highestTarget.mWinAnimator.isAnimationSet() &&
highestTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer) {
// If the window we are currently targeting is involved
// with an animation, and it is on top of the next target
@@ -2275,7 +2274,7 @@
+ " mRemoveOnExit=" + win.mRemoveOnExit
+ " mHasSurface=" + win.mHasSurface
+ " surfaceShowing=" + win.mWinAnimator.getShown()
- + " isAnimating=" + win.mWinAnimator.isAnimating()
+ + " isAnimationSet=" + win.mWinAnimator.isAnimationSet()
+ " app-animation="
+ (win.mAppToken != null ? win.mAppToken.mAppAnimator.animation : null)
+ " mWillReplaceWindow=" + win.mWillReplaceWindow
@@ -2339,7 +2338,7 @@
}
}
final boolean isAnimating =
- winAnimator.isAnimating() && !winAnimator.isDummyAnimation();
+ winAnimator.isAnimationSet() && !winAnimator.isDummyAnimation();
final boolean lastWindowIsStartingWindow = startingWindow && appToken != null
&& appToken.allAppWindows.size() == 1;
// We delay the removal of a window if it has a showing surface that can be used to run
@@ -2924,7 +2923,7 @@
focusMayChange = isDefaultDisplay;
win.mAnimatingExit = true;
win.mWinAnimator.mAnimating = true;
- } else if (win.mWinAnimator.isAnimating()) {
+ } else if (win.mWinAnimator.isAnimationSet()) {
// Currently in a hide animation... turn this into
// an exit.
win.mAnimatingExit = true;
@@ -3281,7 +3280,7 @@
WindowState win = wtoken.windows.get(i);
displayContent = win.getDisplayContent();
- if (win.mWinAnimator.isAnimating()) {
+ if (win.mWinAnimator.isAnimationSet()) {
delayed = true;
}
@@ -4297,7 +4296,7 @@
}
for (int i = wtoken.allAppWindows.size() - 1; i >= 0 && !delayed; i--) {
- if (wtoken.allAppWindows.get(i).mWinAnimator.isWindowAnimating()) {
+ if (wtoken.allAppWindows.get(i).mWinAnimator.isWindowAnimationSet()) {
delayed = true;
}
}
@@ -9101,7 +9100,7 @@
void updateResizingWindows(final WindowState w) {
final WindowStateAnimator winAnimator = w.mWinAnimator;
- if (w.mHasSurface && w.mLayoutSeq == mLayoutSeq) {
+ if (w.mHasSurface && w.mLayoutSeq == mLayoutSeq && !w.isGoneForLayoutLw()) {
w.setInsetsChanged();
boolean configChanged = w.isConfigChanged();
if (DEBUG_CONFIGURATION && configChanged) {
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 8c29c9b..f603995 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -291,21 +291,33 @@
}
}
- /** Is the window or its container currently animating? */
- boolean isAnimating() {
+ /**
+ * Is the window or its container currently set to animate or currently animating?
+ */
+ boolean isAnimationSet() {
return mAnimation != null
|| (mAttachedWinAnimator != null && mAttachedWinAnimator.mAnimation != null)
|| (mAppAnimator != null && mAppAnimator.isAnimating());
}
+ /**
+ * @return whether an animation is about to start, i.e. the animation is set already but we
+ * haven't processed the first frame yet.
+ */
+ boolean isAnimationStarting() {
+ return isAnimationSet() && !mAnimating;
+ }
+
/** Is the window animating the DummyAnimation? */
boolean isDummyAnimation() {
return mAppAnimator != null
&& mAppAnimator.animation == sDummyAnimation;
}
- /** Is this window currently set to animate or currently animating? */
- boolean isWindowAnimating() {
+ /**
+ * Is this window currently set to animate or currently animating?
+ */
+ boolean isWindowAnimationSet() {
return mAnimation != null;
}
@@ -340,7 +352,7 @@
// there is more animation to run.
boolean stepAnimationLocked(long currentTime) {
// Save the animation state as it was before this step so WindowManagerService can tell if
- // we just started or just stopped animating by comparing mWasAnimating with isAnimating().
+ // we just started or just stopped animating by comparing mWasAnimating with isAnimationSet().
mWasAnimating = mAnimating;
final DisplayContent displayContent = mWin.getDisplayContent();
if (displayContent != null && mService.okToDisplay()) {
@@ -402,7 +414,7 @@
// Little trick to get through the path below to act like
// we have finished an animation.
mAnimating = true;
- } else if (isAnimating()) {
+ } else if (isAnimationSet()) {
mAnimating = true;
}
} else if (mAnimation != null) {
@@ -476,7 +488,7 @@
TAG, "finishExit in " + this
+ ": exiting=" + mWin.mAnimatingExit
+ " remove=" + mWin.mRemoveOnExit
- + " windowAnimating=" + isWindowAnimating());
+ + " windowAnimating=" + isWindowAnimationSet());
if (!mWin.mChildWindows.isEmpty()) {
// Copying to a different list as multiple children can be removed.
@@ -499,7 +511,7 @@
}
}
- if (!isWindowAnimating()) {
+ if (!isWindowAnimationSet()) {
//TODO (multidisplay): Accessibility is supported only for the default display.
if (mService.mAccessibilityController != null
&& mWin.getDisplayId() == DEFAULT_DISPLAY) {
@@ -511,7 +523,7 @@
return;
}
- if (isWindowAnimating()) {
+ if (isWindowAnimationSet()) {
return;
}
@@ -1310,7 +1322,7 @@
final int stackClip = resolveStackClip();
// It's animating and we don't want to clip it to stack bounds during animation - abort.
- if (isAnimating() && stackClip == STACK_CLIP_NONE) {
+ if (isAnimationSet() && stackClip == STACK_CLIP_NONE) {
return;
}
@@ -1332,7 +1344,7 @@
// If we are animating, we either apply the clip before applying all the animation
// transformation or after all the transformation.
- final boolean useFinalClipRect = isAnimating() && stackClip == STACK_CLIP_AFTER_ANIM;
+ final boolean useFinalClipRect = isAnimationSet() && stackClip == STACK_CLIP_AFTER_ANIM;
// We need to do some acrobatics with surface position, because their clip region is
// relative to the inside of the surface, but the stack bounds aren't.
@@ -1507,7 +1519,7 @@
w.mToken.hasVisible = true;
}
} else {
- if (DEBUG_ANIM && isAnimating()) {
+ if (DEBUG_ANIM && isAnimationSet()) {
Slog.v(TAG, "prepareSurface: No changes in animation for " + this);
}
displayed = true;
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 928fcc0..8937f09 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -10,7 +10,6 @@
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
-import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
@@ -762,13 +761,15 @@
}
}
}
- if (!winAnimator.isAnimating()) {
+ if (!winAnimator.isAnimationStarting()) {
// Updates the shown frame before we set up the surface. This is needed
// because the resizing could change the top-left position (in addition to
// size) of the window. setSurfaceBoundariesLocked uses mShownPosition to
- // position the surface. We only apply it to windows that aren't animating,
- // because we depend on the animation to calculate the correct shown frame
- // on the next animation step.
+ // position the surface.
+ //
+ // If an animation is being started, we can't call this method because the
+ // animation hasn't processed its initial transformation yet, but in general
+ // we do want to update the position if the window is animating.
winAnimator.computeShownFrameLocked();
}
winAnimator.setSurfaceBoundariesLocked(recoveringMemory);
@@ -792,7 +793,7 @@
if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
Slog.v(TAG, "Eval win " + w + ": isDrawn="
+ w.isDrawnLw()
- + ", isAnimating=" + winAnimator.isAnimating());
+ + ", isAnimationSet=" + winAnimator.isAnimationSet());
if (!w.isDrawnLw()) {
Slog.v(TAG, "Not displayed: s="
+ winAnimator.mSurfaceController
@@ -943,7 +944,8 @@
// windows, since that means "perform layout as normal,
// just don't display").
if (!gone || !win.mHaveFrame || win.mLayoutNeeded
- || ((win.isConfigChanged() || win.setInsetsChanged()) &&
+ || ((win.isConfigChanged() || win.setInsetsChanged())
+ && !win.isGoneForLayoutLw() &&
((win.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 ||
(win.mHasSurface && win.mAppToken != null &&
win.mAppToken.layoutConfigChanges)))) {