Run animation *after* property sync

VectorDrawable contains properties that can be mofidied from both
UI thread and RenderThread. The two sets of properties are synced
during prepareTree. Previously VD animations ran before prepareTree,
as a result, during prepareTree the property sync overwrote some
of the animatable properties. In other words, the first frame of
the animation wasn't correct. An example is in battery saver mode
when the animation only has one frame to animate (0-duration), the
end result looked wrong.

This CL moves the VD animation to after prepareTree to solve the
problem mentioned above. Meanwhile, in order to signal which
VD will be animated so as to have them properly damaged, all VDs
with running animators are marked dirty.

Bug: 30226711
Change-Id: I831dae9abb2908876c935b9be4c11dfd09452d5c
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 037ca73..3669da8 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -195,10 +195,13 @@
             // the animation list, 2) post a delayed message to end them at end time so their
             // listeners can receive the corresponding callbacks.
             anim->getVectorDrawable()->setPropertyChangeWillBeConsumed(false);
+            // Mark the VD dirty so it will damage itself during prepareTree.
+            anim->getVectorDrawable()->markDirty();
         }
         if (info.mode == TreeInfo::MODE_FULL) {
             for (auto &anim : mPausedVDAnimators) {
                 anim->getVectorDrawable()->setPropertyChangeWillBeConsumed(false);
+                anim->getVectorDrawable()->markDirty();
             }
         }
         // TODO: This is hacky
@@ -210,34 +213,6 @@
         info.windowInsetLeft = 0;
         info.windowInsetTop = 0;
         info.errorHandler = nullptr;
-
-        for (auto it = mRunningVDAnimators.begin(); it != mRunningVDAnimators.end();) {
-            if (!(*it)->getVectorDrawable()->getPropertyChangeWillBeConsumed()) {
-                // Vector Drawable is not in the display list, we should remove this animator from
-                // the list, put it in the paused list, and post a delayed message to end the
-                // animator.
-                detachVectorDrawableAnimator(it->get());
-                mPausedVDAnimators.insert(*it);
-                it = mRunningVDAnimators.erase(it);
-            } else {
-                it++;
-            }
-        }
-
-        if (info.mode == TreeInfo::MODE_FULL) {
-            // Check whether any paused animator's target is back in Display List. If so, put the
-            // animator back in the running list.
-            for (auto it = mPausedVDAnimators.begin(); it != mPausedVDAnimators.end();) {
-                if ((*it)->getVectorDrawable()->getPropertyChangeWillBeConsumed()) {
-                    mRunningVDAnimators.insert(*it);
-                    it = mPausedVDAnimators.erase(it);
-                } else {
-                    it++;
-                }
-            }
-        }
-        info.out.hasAnimations |= !mRunningVDAnimators.empty();
-
     }
 
     void sendMessage(const sp<MessageHandler>& handler) {
@@ -275,7 +250,14 @@
         mPendingAnimatingRenderNodes.clear();
     }
 
-    void runVectorDrawableAnimators(AnimationContext* context, TreeInfo::TraversalMode mode) {
+    // Run VectorDrawable animators after prepareTree.
+    void runVectorDrawableAnimators(AnimationContext* context, TreeInfo& info) {
+        // Push staging.
+        if (info.mode == TreeInfo::MODE_FULL) {
+            pushStagingVectorDrawableAnimators(context);
+        }
+
+        // Run the animators in the running list.
         for (auto it = mRunningVDAnimators.begin(); it != mRunningVDAnimators.end();) {
             if ((*it)->animate(*context)) {
                 it = mRunningVDAnimators.erase(it);
@@ -284,7 +266,8 @@
             }
         }
 
-        if (mode == TreeInfo::MODE_FULL) {
+        // Run the animators in paused list during full sync.
+        if (info.mode == TreeInfo::MODE_FULL) {
             // During full sync we also need to pulse paused animators, in case their targets
             // have been added back to the display list. All the animators that passed the
             // scheduled finish time will be removed from the paused list.
@@ -297,6 +280,42 @@
                 }
             }
         }
+
+        // Move the animators with a target not in DisplayList to paused list.
+        for (auto it = mRunningVDAnimators.begin(); it != mRunningVDAnimators.end();) {
+            if (!(*it)->getVectorDrawable()->getPropertyChangeWillBeConsumed()) {
+                // Vector Drawable is not in the display list, we should remove this animator from
+                // the list, put it in the paused list, and post a delayed message to end the
+                // animator.
+                detachVectorDrawableAnimator(it->get());
+                mPausedVDAnimators.insert(*it);
+                it = mRunningVDAnimators.erase(it);
+            } else {
+                it++;
+            }
+        }
+
+        // Move the animators with a target in DisplayList from paused list to running list, and
+        // trim paused list.
+        if (info.mode == TreeInfo::MODE_FULL) {
+            // Check whether any paused animator's target is back in Display List. If so, put the
+            // animator back in the running list.
+            for (auto it = mPausedVDAnimators.begin(); it != mPausedVDAnimators.end();) {
+                if ((*it)->getVectorDrawable()->getPropertyChangeWillBeConsumed()) {
+                    mRunningVDAnimators.insert(*it);
+                    it = mPausedVDAnimators.erase(it);
+                } else {
+                    it++;
+                }
+            }
+            // Trim paused VD animators at full sync, so that when Java loses reference to an
+            // animator, we know we won't be requested to animate it any more, then we remove such
+            // animators from the paused list so they can be properly freed. We also remove the
+            // animators from paused list when the time elapsed since start has exceeded duration.
+            trimPausedVDAnimators(context);
+        }
+
+        info.out.hasAnimations |= !mRunningVDAnimators.empty();
     }
 
     void trimPausedVDAnimators(AnimationContext* context) {
@@ -387,29 +406,13 @@
             mRootNode->attachPendingVectorDrawableAnimators();
         }
         AnimationContext::startFrame(mode);
-        // Run VectorDrawable animators in the beginning of the frame instead of during prepareTree,
-        // because one VD can be in multiple render nodes' display list. So it's more simple to
-        // run them all at once before prepareTree than running them or checking whether they have
-        // already ran in each RenderNode. Note that these animators don't damage the RenderNodes.
-        // The damaging is done in prepareTree as needed after checking whether a VD has been
-        // modified.
-        if (mode == TreeInfo::MODE_FULL) {
-            mRootNode->pushStagingVectorDrawableAnimators(this);
-        }
-        mRootNode->runVectorDrawableAnimators(this, mode);
     }
 
     // Runs any animations still left in mCurrentFrameAnimations
     virtual void runRemainingAnimations(TreeInfo& info) {
         AnimationContext::runRemainingAnimations(info);
+        mRootNode->runVectorDrawableAnimators(this, info);
         postOnFinishedEvents();
-        if (info.mode == TreeInfo::MODE_FULL) {
-            // Trim paused VD animators at full sync, so that when Java loses reference to an
-            // animator, we know we won't be requested to animate it any more, then we remove such
-            // animators from the paused list so they can be properly freed. We also remove the
-            // animators from paused list when the time elapsed since start has exceeded duration.
-            mRootNode->trimPausedVDAnimators(this);
-        }
     }
 
     virtual void detachAnimators() override {
diff --git a/libs/hwui/VectorDrawable.h b/libs/hwui/VectorDrawable.h
index e67dfdd..a0c3d9d 100644
--- a/libs/hwui/VectorDrawable.h
+++ b/libs/hwui/VectorDrawable.h
@@ -678,6 +678,7 @@
     TreeProperties* mutateProperties() { return &mProperties; }
 
     // This should always be called from RT.
+    void markDirty() { mCache.dirty = true; }
     bool isDirty() const { return mCache.dirty; }
     bool getPropertyChangeWillBeConsumed() const { return mWillBeConsumed; }
     void setPropertyChangeWillBeConsumed(bool willBeConsumed) { mWillBeConsumed = willBeConsumed; }