RenderThread animator support

Change-Id: Icf29098edfdaf7ed550bbe9d49e9eaefb4167084
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 838e5ac..dcd6bda 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -18,6 +18,8 @@
 
 #include "RenderNode.h"
 
+#include <algorithm>
+
 #include <SkCanvas.h>
 #include <algorithm>
 
@@ -54,7 +56,8 @@
         : mNeedsPropertiesSync(false)
         , mNeedsDisplayListDataSync(false)
         , mDisplayListData(0)
-        , mStagingDisplayListData(0) {
+        , mStagingDisplayListData(0)
+        , mNeedsAnimatorsSync(false) {
 }
 
 RenderNode::~RenderNode() {
@@ -97,15 +100,32 @@
 }
 
 void RenderNode::prepareTreeImpl(TreeInfo& info) {
-    pushStagingChanges(info);
+    if (info.performStagingPush) {
+        pushStagingChanges(info);
+    }
+    if (info.evaluateAnimations) {
+        evaluateAnimations(info);
+    }
     prepareSubTree(info, mDisplayListData);
 }
 
+static bool is_finished(const sp<RenderPropertyAnimator>& animator) {
+    return animator->isFinished();
+}
+
 void RenderNode::pushStagingChanges(TreeInfo& info) {
     if (mNeedsPropertiesSync) {
         mNeedsPropertiesSync = false;
         mProperties = mStagingProperties;
     }
+    if (mNeedsAnimatorsSync) {
+        mAnimators.reserve(mStagingAnimators.size());
+        std::vector< sp<RenderPropertyAnimator> >::iterator it;
+        // hint: this means copy_if_not()
+        it = std::remove_copy_if(mStagingAnimators.begin(), mStagingAnimators.end(),
+                mAnimators.begin(), is_finished);
+        mAnimators.resize(std::distance(mAnimators.begin(), it));
+    }
     if (mNeedsDisplayListDataSync) {
         mNeedsDisplayListDataSync = false;
         // Do a push pass on the old tree to handle freeing DisplayListData
@@ -119,6 +139,34 @@
     }
 }
 
+class AnimateFunctor {
+public:
+    AnimateFunctor(RenderProperties* target, TreeInfo& info)
+            : mTarget(target), mInfo(info) {}
+
+    bool operator() (sp<RenderPropertyAnimator>& animator) {
+        bool finished = animator->animate(mTarget, mInfo);
+        if (finished && mInfo.animationListener) {
+            mInfo.animationListener->onAnimationFinished(animator);
+        }
+        return finished;
+    }
+private:
+    RenderProperties* mTarget;
+    TreeInfo& mInfo;
+};
+
+void RenderNode::evaluateAnimations(TreeInfo& info) {
+    if (!mAnimators.size()) return;
+
+    AnimateFunctor functor(&mProperties, info);
+    std::vector< sp<RenderPropertyAnimator> >::iterator newEnd;
+    newEnd = std::remove_if(mAnimators.begin(), mAnimators.end(), functor);
+    mAnimators.erase(newEnd, mAnimators.end());
+    mProperties.updateMatrix();
+    info.hasAnimations |= mAnimators.size();
+}
+
 void RenderNode::prepareSubTree(TreeInfo& info, DisplayListData* subtree) {
     if (subtree) {
         TextureCache& cache = Caches::getInstance().textureCache;