Don't leak windows on removal with dummy animations

Dummy animations might never end. Do not hold a window removal
for it.

Bug: 21403998
Change-Id: Ie907d31f51e130e245a70249a983d490f3d42b21
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 5c9f87e..bd2e002 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2724,14 +2724,16 @@
                 }
             }
             final AppWindowToken appToken = win.mAppToken;
+            // Prevent an immediate window exit only for a real animation, ignoring e.g.
+            // dummy animations.
+            final boolean inAnimation = win.mWinAnimator.isWindowAnimatingNow();
             // The starting window is the last window in this app token and it isn't animating.
             // Allow it to be removed now as there is no additional window or animation that will
             // trigger its removal.
             final boolean lastWinStartingNotAnimating = startingWindow && appToken!= null
-                    && appToken.allAppWindows.size() == 1 && !win.mWinAnimator.isWindowAnimating();
-            if (!lastWinStartingNotAnimating && (win.mExiting || win.mWinAnimator.isAnimating())) {
+                    && appToken.allAppWindows.size() == 1 && !inAnimation;
+            if (!lastWinStartingNotAnimating && (win.mExiting || inAnimation)) {
                 // The exit animation is running... wait for it!
-                //Slog.i(TAG, "*** Running exit animation...");
                 win.mExiting = true;
                 win.mRemoveOnExit = true;
                 final DisplayContent displayContent = win.getDisplayContent();
@@ -2747,7 +2749,6 @@
                 if (focusChanged) {
                     mInputMonitor.updateInputWindowsLw(false /*force*/);
                 }
-                //dump();
                 Binder.restoreCallingIdentity(origId);
                 return;
             }
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index e9023fd..b42c8eb 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -251,11 +251,21 @@
                 && mAppAnimator.animation == AppWindowAnimator.sDummyAnimation;
     }
 
-    /** Is this window currently animating? */
+    /** Is this window currently set to animate or currently animating?
+     *  NOTE: The method will return true for cases where the window isn't currently animating, but
+     *  is set to animate. i.e. if the window animation is currently set to a dummy placeholder
+     *  animation. Use {@link #isWindowAnimatingNow} to know if the window is currently running a
+     *  real animation. */
     boolean isWindowAnimating() {
         return mAnimation != null;
     }
 
+    /** Is the window performing a real animation and not a dummy which is only waiting for an
+     * an animation to start? */
+    boolean isWindowAnimatingNow() {
+        return isWindowAnimating() && !isDummyAnimation();
+    }
+
     void cancelExitAnimationForNextAnimationLocked() {
         if (mAnimation != null) {
             mAnimation.cancel();