Enable activity rendering during window animations

A change was made back in ICS that prevents the view hierarchy from rendering
during window animations. Specifically, it allows the hierarchy to render once (to draw
the results of its first layout), but further drawing is suppressed at the
ViewRoot/performTraversals level until the window animation is complete.

This change was introduced to avoid jank problems that were resulting from
thrashing the GPU by issuing drawing commands from multiple processes simultaneously,
and limited the number of rendering processes to mainly the system server (and
possibly the System UI), which allowed window animations to be much smoother.

This fix contributed to another source of jank, however, in which applications
which attempt to animate when they first appear will not render any frames of
animations until the window animation is done, resulting is a snapping to the resulting
state once the window animations are complete.

Meanwhile, hardware has gotten faster and GPUs have gotten better, and it is time to
revisit this logic. This change disables the earlier fix and allows view hierarchies
to draw normally, regardless of whether window animations are taking place.

Issue #22232939 Remove flag that prevents drawing during window animations

Change-Id: I4c960180771ff09a7088abd77b437586e835a991
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index acad496..cc4bcb6 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -80,20 +80,6 @@
             int localValue, int localChanges);
 
     /**
-     * The window is beginning to animate. The application should stop drawing frames until the
-     * window is not animating anymore, indicated by being called {@link #windowEndAnimating}.
-     *
-     * @param remainingFrameCount how many frames the app might still draw before stopping drawing;
-     *                            pass -1 to let it continue drawing
-     */
-    void onAnimationStarted(int remainingFrameCount);
-
-    /**
-     * The window has ended animating. See {@link #onAnimationStarted}.
-     */
-    void onAnimationStopped();
-
-    /**
      * Called for non-application windows when the enter animation has completed.
      */
     void dispatchWindowShown();
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 7cf23e7..72bbf40 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -238,11 +238,7 @@
     boolean mNewSurfaceNeeded;
     boolean mHasHadWindowFocus;
     boolean mLastWasImTarget;
-    boolean mWindowsAnimating;
-    boolean mDrawDuringWindowsAnimating;
 
-    /** How many frames the app is still allowed to draw when a window animation is happening. */
-    private int mRemainingFrameCount;
     boolean mIsDrawing;
     int mLastSystemUiVisibility;
     int mClientWindowLayoutFlags;
@@ -1978,8 +1974,6 @@
             }
         }
 
-        boolean skipDraw = false;
-
         if (mFirst) {
             // handle first focus request
             if (DEBUG_INPUT_RESIZE) Log.v(TAG, "First: mView.hasFocus()="
@@ -1994,11 +1988,6 @@
                             + mView.findFocus());
                 }
             }
-        } else if (mWindowsAnimating) {
-            if (mRemainingFrameCount <= 0) {
-                skipDraw = true;
-            }
-            mRemainingFrameCount--;
         }
 
         final boolean changedVisibility = (viewVisibilityChanged || mFirst) && isViewVisible;
@@ -2043,16 +2032,14 @@
         boolean cancelDraw = mAttachInfo.mTreeObserver.dispatchOnPreDraw() || !isViewVisible;
 
         if (!cancelDraw && !newSurface) {
-            if (!skipDraw || mReportNextDraw) {
-                if (mPendingTransitions != null && mPendingTransitions.size() > 0) {
-                    for (int i = 0; i < mPendingTransitions.size(); ++i) {
-                        mPendingTransitions.get(i).startChangingAnimations();
-                    }
-                    mPendingTransitions.clear();
+            if (mPendingTransitions != null && mPendingTransitions.size() > 0) {
+                for (int i = 0; i < mPendingTransitions.size(); ++i) {
+                    mPendingTransitions.get(i).startChangingAnimations();
                 }
-
-                performDraw();
+                mPendingTransitions.clear();
             }
+
+            performDraw();
         } else {
             if (isViewVisible) {
                 // Try again
@@ -2787,16 +2774,6 @@
         return mAttachInfo.mAccessibilityFocusDrawable;
     }
 
-    /**
-     * @hide
-     */
-    public void setDrawDuringWindowsAnimating(boolean value) {
-        mDrawDuringWindowsAnimating = value;
-        if (value) {
-            handleDispatchWindowAnimationStopped();
-        }
-    }
-
     boolean scrollToRectOrFocus(Rect rectangle, boolean immediate) {
         final Rect ci = mAttachInfo.mContentInsets;
         final Rect vi = mAttachInfo.mVisibleInsets;
@@ -3160,8 +3137,6 @@
     private final static int MSG_WINDOW_MOVED = 23;
     private final static int MSG_SYNTHESIZE_INPUT_EVENT = 24;
     private final static int MSG_DISPATCH_WINDOW_SHOWN = 25;
-    private final static int MSG_DISPATCH_WINDOW_ANIMATION_STOPPED = 26;
-    private final static int MSG_DISPATCH_WINDOW_ANIMATION_STARTED = 27;
 
     final class ViewRootHandler extends Handler {
         @Override
@@ -3205,10 +3180,6 @@
                     return "MSG_PROCESS_INPUT_EVENTS";
                 case MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST:
                     return "MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST";
-                case MSG_DISPATCH_WINDOW_ANIMATION_STARTED:
-                    return "MSG_DISPATCH_WINDOW_ANIMATION_STARTED";
-                case MSG_DISPATCH_WINDOW_ANIMATION_STOPPED:
-                    return "MSG_DISPATCH_WINDOW_ANIMATION_STOPPED";
                 case MSG_WINDOW_MOVED:
                     return "MSG_WINDOW_MOVED";
                 case MSG_SYNTHESIZE_INPUT_EVENT:
@@ -3429,13 +3400,6 @@
             case MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST: {
                 setAccessibilityFocus(null, null);
             } break;
-            case MSG_DISPATCH_WINDOW_ANIMATION_STARTED: {
-                int remainingFrameCount = msg.arg1;
-                handleDispatchWindowAnimationStarted(remainingFrameCount);
-            } break;
-            case MSG_DISPATCH_WINDOW_ANIMATION_STOPPED: {
-                handleDispatchWindowAnimationStopped();
-            } break;
             case MSG_INVALIDATE_WORLD: {
                 if (mView != null) {
                     invalidateWorld(mView);
@@ -4048,9 +4012,6 @@
             if (q.mEvent instanceof KeyEvent) {
                 return processKeyEvent(q);
             } else {
-                // If delivering a new non-key event, make sure the window is
-                // now allowed to start updating.
-                handleDispatchWindowAnimationStopped();
                 final int source = q.mEvent.getSource();
                 if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
                     return processPointerEvent(q);
@@ -4077,12 +4038,6 @@
         private int processKeyEvent(QueuedInputEvent q) {
             final KeyEvent event = (KeyEvent)q.mEvent;
 
-            if (event.getAction() != KeyEvent.ACTION_UP) {
-                // If delivering a new key event, make sure the window is
-                // now allowed to start updating.
-                handleDispatchWindowAnimationStopped();
-            }
-
             // Deliver the key to the view hierarchy.
             if (mView.dispatchKeyEvent(event)) {
                 return FINISH_HANDLED;
@@ -5297,22 +5252,6 @@
         }
     }
 
-    public void handleDispatchWindowAnimationStarted(int remainingFrameCount) {
-        if (!mDrawDuringWindowsAnimating && remainingFrameCount != -1) {
-            mRemainingFrameCount = remainingFrameCount;
-            mWindowsAnimating = true;
-        }
-    }
-
-    public void handleDispatchWindowAnimationStopped() {
-        if (mWindowsAnimating) {
-            mWindowsAnimating = false;
-            if (!mDirty.isEmpty() || mIsAnimating || mFullRedrawNeeded)  {
-                scheduleTraversals();
-            }
-        }
-    }
-
     public void handleDispatchWindowShown() {
         mAttachInfo.mTreeObserver.dispatchOnWindowShown();
     }
@@ -6224,15 +6163,6 @@
         mHandler.sendMessage(mHandler.obtainMessage(MSG_DISPATCH_SYSTEM_UI_VISIBILITY, args));
     }
 
-    public void dispatchWindowAnimationStarted(int remainingFrameCount) {
-        mHandler.obtainMessage(MSG_DISPATCH_WINDOW_ANIMATION_STARTED,
-                remainingFrameCount, 0 /* unused */).sendToTarget();
-    }
-
-    public void dispatchWindowAnimationStopped() {
-        mHandler.sendEmptyMessage(MSG_DISPATCH_WINDOW_ANIMATION_STOPPED);
-    }
-
     public void dispatchCheckFocus() {
         if (!mHandler.hasMessages(MSG_CHECK_FOCUS)) {
             // This will result in a call to checkFocus() below.
@@ -6802,22 +6732,6 @@
         }
 
         @Override
-        public void onAnimationStarted(int remainingFrameCount) {
-            final ViewRootImpl viewAncestor = mViewAncestor.get();
-            if (viewAncestor != null) {
-                viewAncestor.dispatchWindowAnimationStarted(remainingFrameCount);
-            }
-        }
-
-        @Override
-        public void onAnimationStopped() {
-            final ViewRootImpl viewAncestor = mViewAncestor.get();
-            if (viewAncestor != null) {
-                viewAncestor.dispatchWindowAnimationStopped();
-            }
-        }
-
-        @Override
         public void dispatchWindowShown() {
             final ViewRootImpl viewAncestor = mViewAncestor.get();
             if (viewAncestor != null) {
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index 3eeabcd..07bfce7 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -100,14 +100,6 @@
     }
 
     @Override
-    public void onAnimationStarted(int remainingFrameCount) {
-    }
-
-    @Override
-    public void onAnimationStopped() {
-    }
-
-    @Override
     public void dispatchWindowShown() {
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 011889a..33e514d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -187,15 +187,6 @@
         mBarTransitions = new NavigationBarTransitions(this);
     }
 
-    @Override
-    protected void onAttachedToWindow() {
-        super.onAttachedToWindow();
-        ViewRootImpl root = getViewRootImpl();
-        if (root != null) {
-            root.setDrawDuringWindowsAnimating(true);
-        }
-    }
-
     public BarTransitions getBarTransitions() {
         return mBarTransitions;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index cfd3358..35a17e4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -144,13 +144,6 @@
     protected void onAttachedToWindow () {
         super.onAttachedToWindow();
 
-        // We really need to be able to animate while window animations are going on
-        // so that activities may be started asynchronously from panel animations
-        final ViewRootImpl root = getViewRootImpl();
-        if (root != null) {
-            root.setDrawDuringWindowsAnimating(true);
-        }
-
         // We need to ensure that our window doesn't suffer from overdraw which would normally
         // occur if our window is translucent. Since we are drawing the whole window anyway with
         // the scrim, we don't need the window to be cleared in the beginning.
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index ab1bf20..5138269 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -272,25 +272,6 @@
                 winAnimator.mWasAnimating = nowAnimating;
                 mAnimating |= nowAnimating;
 
-                boolean appWindowAnimating = winAnimator.mAppAnimator != null
-                        && winAnimator.mAppAnimator.animating;
-                boolean wasAppWindowAnimating = winAnimator.mAppAnimator != null
-                        && winAnimator.mAppAnimator.wasAnimating;
-                boolean anyAnimating = appWindowAnimating || nowAnimating;
-                boolean anyWasAnimating = wasAppWindowAnimating || wasAnimating;
-
-                try {
-                    if (anyAnimating && !anyWasAnimating) {
-                        win.mClient.onAnimationStarted(winAnimator.mAnimatingMove ? -1
-                                : winAnimator.mKeyguardGoingAwayAnimation ? 1
-                                : 0);
-                    } else if (!anyAnimating && anyWasAnimating) {
-                        win.mClient.onAnimationStopped();
-                    }
-                } catch (RemoteException e) {
-                    Slog.w(TAG, "Failed to dispatch window animation state change.", e);
-                }
-
                 if (WindowManagerService.DEBUG_WALLPAPER) {
                     Slog.v(TAG, win + ": wasAnimating=" + wasAnimating +
                             ", nowAnimating=" + nowAnimating);
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index ed53501..722ef9f 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -290,6 +290,9 @@
     // This must be called while inside a transaction.  Returns true if
     // 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().
+        mWasAnimating = mAnimating;
         final DisplayContent displayContent = mWin.getDisplayContent();
         if (displayContent != null && mService.okToDisplay()) {
             // We will run animations as long as the display isn't frozen.
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
index 771c3c8..c2d8d0c 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
@@ -91,14 +91,6 @@
     }
 
     @Override
-    public void onAnimationStarted(int remainingFrameCount) {
-    }
-
-    @Override
-    public void onAnimationStopped() {
-    }
-
-    @Override
     public void dispatchWindowShown() {
     }