Delay calling uiDoneClosing until all animations are finished

uiDoneClosing sets the index which does a lot of work, so if we are also
playing an animation during that, the animation quality suffers quite a
bit. With this change, we check whether there are any ongoing layout
animations and postpone the call until the animation finishes.

BUG=960427

Change-Id: I8a37e7cd37a2ec3758c3150d4e2b1715908e4358
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1625839
Commit-Queue: Yusuf Ozuysal <yusufo@chromium.org>
Reviewed-by: Wei-Yin Chen (陳威尹) <wychen@chromium.org>
Reviewed-by: Matthew Jones <mdjones@chromium.org>
Cr-Commit-Position: refs/heads/master@{#663280}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayoutBase.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayoutBase.java
index af41322..95dee59 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayoutBase.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayoutBase.java
@@ -4,6 +4,8 @@
 
 package org.chromium.chrome.browser.compositor.layouts.phone;
 
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
 import android.content.Context;
 import android.graphics.Rect;
 import android.graphics.RectF;
@@ -810,7 +812,27 @@
      * @param canUndo   Whether or not this close can be undone.
      * @param incognito Whether or not this was for the incognito stack or not.
      */
-    public void uiDoneClosingTab(long time, int id, boolean canUndo, boolean incognito) {
+    public void uiDoneClosingTab(
+            final long time, final int id, boolean canUndo, final boolean incognito) {
+        // If there are any ongoing layout animations, postpone this until they are done since
+        // closeTabById does a lot of work.
+        for (int i = 0; i < mLayoutAnimations.size(); i++) {
+            if (mLayoutAnimations.get(i).first.isRunning()) {
+                final boolean cachedCanUndo = canUndo;
+                final AnimatorListenerAdapter adapter = new AnimatorListenerAdapter() {
+                    @Override
+                    public void onAnimationEnd(Animator animation) {
+                        uiDoneClosingTab(time, id, cachedCanUndo, incognito);
+                        animation.removeListener(this);
+                    }
+                };
+                mLayoutAnimations.get(i).first.addListener(adapter);
+                return;
+            }
+        }
+
+        assert !isLayoutAnimating();
+
         // If homepage is enabled and there is a maximum of 1 tab in both models
         // (this is the last tab), the tab closure cannot be undone.
         canUndo &= !(HomepageManager.shouldCloseAppWithZeroTabs()