Add CanvasProperty for drawCircle

Change-Id: Icbcc030f5033d2094e567d7c519b9d672f2aac1c
diff --git a/libs/hwui/Animator.cpp b/libs/hwui/Animator.cpp
index ee16586..6a3003e 100644
--- a/libs/hwui/Animator.cpp
+++ b/libs/hwui/Animator.cpp
@@ -20,130 +20,13 @@
 
 #include <set>
 
+#include "RenderNode.h"
 #include "RenderProperties.h"
 
 namespace android {
 namespace uirenderer {
 
 /************************************************************
- *  Private header
- ************************************************************/
-
-typedef void (RenderProperties::*SetFloatProperty)(float value);
-typedef float (RenderProperties::*GetFloatProperty)() const;
-
-struct PropertyAccessors {
-    GetFloatProperty getter;
-    SetFloatProperty setter;
-};
-
-// Maps RenderProperty enum to accessors
-static const PropertyAccessors PROPERTY_ACCESSOR_LUT[] = {
-    {&RenderProperties::getTranslationX, &RenderProperties::setTranslationX },
-    {&RenderProperties::getTranslationY, &RenderProperties::setTranslationY },
-    {&RenderProperties::getTranslationZ, &RenderProperties::setTranslationZ },
-    {&RenderProperties::getScaleX, &RenderProperties::setScaleX },
-    {&RenderProperties::getScaleY, &RenderProperties::setScaleY },
-    {&RenderProperties::getRotation, &RenderProperties::setRotation },
-    {&RenderProperties::getRotationX, &RenderProperties::setRotationX },
-    {&RenderProperties::getRotationY, &RenderProperties::setRotationY },
-    {&RenderProperties::getX, &RenderProperties::setX },
-    {&RenderProperties::getY, &RenderProperties::setY },
-    {&RenderProperties::getZ, &RenderProperties::setZ },
-    {&RenderProperties::getAlpha, &RenderProperties::setAlpha },
-};
-
-// Helper class to contain generic animator helpers
-class BaseAnimator {
-public:
-    BaseAnimator();
-    virtual ~BaseAnimator();
-
-    void setInterpolator(Interpolator* interpolator);
-    void setDuration(nsecs_t durationInMs);
-
-    bool isFinished() { return mPlayState == FINISHED; }
-
-protected:
-    // This is the main animation entrypoint that subclasses should call
-    // to generate the onAnimation* lifecycle events
-    // Returns true if the animation has finished, false otherwise
-    bool animateFrame(nsecs_t frameTime);
-
-    // Called when PlayState switches from PENDING to RUNNING
-    virtual void onAnimationStarted() {}
-    virtual void onAnimationUpdated(float fraction) = 0;
-    virtual void onAnimationFinished() {}
-
-private:
-    enum PlayState {
-        PENDING,
-        RUNNING,
-        FINISHED,
-    };
-
-    Interpolator* mInterpolator;
-    PlayState mPlayState;
-    long mStartTime;
-    long mDuration;
-};
-
-// Hide the base classes & private bits from the exported RenderPropertyAnimator
-// in this Impl class so that subclasses of RenderPropertyAnimator don't require
-// knowledge of the inner guts but only the public virtual methods.
-// Animates a single property
-class RenderPropertyAnimatorImpl : public BaseAnimator {
-public:
-    RenderPropertyAnimatorImpl(GetFloatProperty getter, SetFloatProperty setter,
-            RenderPropertyAnimator::DeltaValueType deltaType, float delta);
-    ~RenderPropertyAnimatorImpl();
-
-    bool animate(RenderProperties* target, TreeInfo& info);
-
-protected:
-    virtual void onAnimationStarted();
-    virtual void onAnimationUpdated(float fraction);
-
-private:
-    // mTarget is only valid inside animate()
-    RenderProperties* mTarget;
-    GetFloatProperty mGetter;
-    SetFloatProperty mSetter;
-
-    RenderPropertyAnimator::DeltaValueType mDeltaValueType;
-    float mDeltaValue;
-    float mFromValue;
-};
-
-RenderPropertyAnimator::RenderPropertyAnimator(RenderProperty property,
-        DeltaValueType deltaType, float deltaValue) {
-    PropertyAccessors pa = PROPERTY_ACCESSOR_LUT[property];
-    mImpl = new RenderPropertyAnimatorImpl(pa.getter, pa.setter, deltaType, deltaValue);
-}
-
-RenderPropertyAnimator::~RenderPropertyAnimator() {
-    delete mImpl;
-    mImpl = NULL;
-}
-
-void RenderPropertyAnimator::setInterpolator(Interpolator* interpolator) {
-    mImpl->setInterpolator(interpolator);
-}
-
-void RenderPropertyAnimator::setDuration(nsecs_t durationInMs) {
-    mImpl->setDuration(durationInMs);
-}
-
-bool RenderPropertyAnimator::isFinished() {
-    return mImpl->isFinished();
-}
-
-bool RenderPropertyAnimator::animate(RenderProperties* target, TreeInfo& info) {
-    return mImpl->animate(target, info);
-}
-
-
-/************************************************************
  *  Base animator
  ************************************************************/
 
@@ -168,10 +51,10 @@
     mDuration = duration;
 }
 
-bool BaseAnimator::animateFrame(nsecs_t frameTime) {
+bool BaseAnimator::animateFrame(TreeInfo& info) {
     if (mPlayState == PENDING) {
         mPlayState = RUNNING;
-        mStartTime = frameTime;
+        mStartTime = info.frameTimeMs;
         // No interpolator was set, use the default
         if (!mInterpolator) {
             setInterpolator(Interpolator::createDefaultInterpolator());
@@ -181,7 +64,7 @@
 
     float fraction = 1.0f;
     if (mPlayState == RUNNING) {
-        fraction = mDuration > 0 ? (float)(frameTime - mStartTime) / mDuration : 1.0f;
+        fraction = mDuration > 0 ? (float)(info.frameTimeMs - mStartTime) / mDuration : 1.0f;
         if (fraction >= 1.0f) {
             fraction = 1.0f;
             mPlayState = FINISHED;
@@ -192,48 +75,140 @@
 
     if (mPlayState == FINISHED) {
         onAnimationFinished();
+        callOnFinishedListener(info);
         return true;
     }
     return false;
 }
 
+void BaseAnimator::callOnFinishedListener(TreeInfo& info) {
+    if (mListener.get()) {
+        if (!info.animationHook) {
+            mListener->onAnimationFinished(this);
+        } else {
+            info.animationHook->callOnFinished(this, mListener.get());
+        }
+    }
+}
+
+/************************************************************
+ *  BaseRenderNodeAnimator
+ ************************************************************/
+
+BaseRenderNodeAnimator::BaseRenderNodeAnimator(
+                BaseRenderNodeAnimator::DeltaValueType deltaType, float delta)
+        : mTarget(0)
+        , mDeltaValueType(deltaType)
+        , mDeltaValue(delta)
+        , mFromValue(-1) {
+}
+
+bool BaseRenderNodeAnimator::animate(RenderNode* target, TreeInfo& info) {
+    mTarget = target;
+    bool finished = animateFrame(info);
+    mTarget = NULL;
+    return finished;
+}
+
+void BaseRenderNodeAnimator::onAnimationStarted() {
+    mFromValue = getValue();
+
+    if (mDeltaValueType == BaseRenderNodeAnimator::ABSOLUTE) {
+        mDeltaValue = (mDeltaValue - mFromValue);
+        mDeltaValueType = BaseRenderNodeAnimator::DELTA;
+    }
+}
+
+void BaseRenderNodeAnimator::onAnimationUpdated(float fraction) {
+    float value = mFromValue + (mDeltaValue * fraction);
+    setValue(value);
+}
+
 /************************************************************
  *  RenderPropertyAnimator
  ************************************************************/
 
-RenderPropertyAnimatorImpl::RenderPropertyAnimatorImpl(
-                GetFloatProperty getter, SetFloatProperty setter,
-                RenderPropertyAnimator::DeltaValueType deltaType, float delta)
-        : mTarget(0)
-        , mGetter(getter)
-        , mSetter(setter)
-        , mDeltaValueType(deltaType)
-        , mDeltaValue(delta)
-        , mFromValue(-1) {
+// Maps RenderProperty enum to accessors
+const RenderPropertyAnimator::PropertyAccessors RenderPropertyAnimator::PROPERTY_ACCESSOR_LUT[] = {
+    {&RenderProperties::getTranslationX, &RenderProperties::setTranslationX },
+    {&RenderProperties::getTranslationY, &RenderProperties::setTranslationY },
+    {&RenderProperties::getTranslationZ, &RenderProperties::setTranslationZ },
+    {&RenderProperties::getScaleX, &RenderProperties::setScaleX },
+    {&RenderProperties::getScaleY, &RenderProperties::setScaleY },
+    {&RenderProperties::getRotation, &RenderProperties::setRotation },
+    {&RenderProperties::getRotationX, &RenderProperties::setRotationX },
+    {&RenderProperties::getRotationY, &RenderProperties::setRotationY },
+    {&RenderProperties::getX, &RenderProperties::setX },
+    {&RenderProperties::getY, &RenderProperties::setY },
+    {&RenderProperties::getZ, &RenderProperties::setZ },
+    {&RenderProperties::getAlpha, &RenderProperties::setAlpha },
+};
+
+RenderPropertyAnimator::RenderPropertyAnimator(RenderProperty property,
+                DeltaValueType deltaType, float deltaValue)
+        : BaseRenderNodeAnimator(deltaType, deltaValue)
+        , mPropertyAccess(PROPERTY_ACCESSOR_LUT[property]) {
 }
 
-RenderPropertyAnimatorImpl::~RenderPropertyAnimatorImpl() {
+float RenderPropertyAnimator::getValue() const {
+    return (target()->animatorProperties().*mPropertyAccess.getter)();
 }
 
-bool RenderPropertyAnimatorImpl::animate(RenderProperties* target, TreeInfo& info) {
-    mTarget = target;
-    bool finished = animateFrame(info.frameTimeMs);
-    mTarget = NULL;
-    return finished;
+void RenderPropertyAnimator::setValue(float value) {
+    (target()->animatorProperties().*mPropertyAccess.setter)(value);
 }
 
-void RenderPropertyAnimatorImpl::onAnimationStarted() {
-    mFromValue = (mTarget->*mGetter)();
+/************************************************************
+ *  CanvasPropertyPrimitiveAnimator
+ ************************************************************/
 
-    if (mDeltaValueType == RenderPropertyAnimator::ABSOLUTE) {
-        mDeltaValue = (mDeltaValue - mFromValue);
-        mDeltaValueType = RenderPropertyAnimator::DELTA;
+CanvasPropertyPrimitiveAnimator::CanvasPropertyPrimitiveAnimator(
+                CanvasPropertyPrimitive* property, DeltaValueType deltaType, float deltaValue)
+        : BaseRenderNodeAnimator(deltaType, deltaValue)
+        , mProperty(property) {
+}
+
+float CanvasPropertyPrimitiveAnimator::getValue() const {
+    return mProperty->value;
+}
+
+void CanvasPropertyPrimitiveAnimator::setValue(float value) {
+    mProperty->value = value;
+}
+
+/************************************************************
+ *  CanvasPropertySkPaintAnimator
+ ************************************************************/
+
+CanvasPropertyPaintAnimator::CanvasPropertyPaintAnimator(
+                CanvasPropertyPaint* property, PaintField field,
+                DeltaValueType deltaType, float deltaValue)
+        : BaseRenderNodeAnimator(deltaType, deltaValue)
+        , mProperty(property)
+        , mField(field) {
+}
+
+float CanvasPropertyPaintAnimator::getValue() const {
+    switch (mField) {
+    case STROKE_WIDTH:
+        return mProperty->value.getStrokeWidth();
+    case ALPHA:
+        return mProperty->value.getAlpha();
     }
+    LOG_ALWAYS_FATAL("Unknown field %d", (int) mField);
+    return -1;
 }
 
-void RenderPropertyAnimatorImpl::onAnimationUpdated(float fraction) {
-    float value = mFromValue + (mDeltaValue * fraction);
-    (mTarget->*mSetter)(value);
+void CanvasPropertyPaintAnimator::setValue(float value) {
+    switch (mField) {
+    case STROKE_WIDTH:
+        mProperty->value.setStrokeWidth(value);
+        return;
+    case ALPHA:
+        mProperty->value.setAlpha(value);
+        return;
+    }
+    LOG_ALWAYS_FATAL("Unknown field %d", (int) mField);
 }
 
 } /* namespace uirenderer */
diff --git a/libs/hwui/Animator.h b/libs/hwui/Animator.h
index 1c8361b..0b074cc 100644
--- a/libs/hwui/Animator.h
+++ b/libs/hwui/Animator.h
@@ -17,18 +17,72 @@
 #define ANIMATOR_H
 
 #include <cutils/compiler.h>
+#include <utils/StrongPointer.h>
 
+#include "CanvasProperty.h"
 #include "Interpolator.h"
 #include "TreeInfo.h"
+#include "utils/Macros.h"
 #include "utils/VirtualLightRefBase.h"
 
 namespace android {
 namespace uirenderer {
 
+class RenderNode;
 class RenderProperties;
-class RenderPropertyAnimatorImpl;
 
-class RenderPropertyAnimator : public VirtualLightRefBase {
+class AnimationListener : public VirtualLightRefBase {
+public:
+    ANDROID_API virtual void onAnimationFinished(BaseAnimator*) = 0;
+protected:
+    ANDROID_API virtual ~AnimationListener() {}
+};
+
+// Helper class to contain generic animator helpers
+class BaseAnimator : public VirtualLightRefBase {
+    PREVENT_COPY_AND_ASSIGN(BaseAnimator);
+public:
+
+    ANDROID_API void setInterpolator(Interpolator* interpolator);
+    ANDROID_API void setDuration(nsecs_t durationInMs);
+    ANDROID_API void setListener(AnimationListener* listener) {
+        mListener = listener;
+    }
+
+    bool isFinished() { return mPlayState == FINISHED; }
+
+protected:
+    BaseAnimator();
+    virtual ~BaseAnimator();
+
+    // This is the main animation entrypoint that subclasses should call
+    // to generate the onAnimation* lifecycle events
+    // Returns true if the animation has finished, false otherwise
+    bool animateFrame(TreeInfo& info);
+
+    // Called when PlayState switches from PENDING to RUNNING
+    virtual void onAnimationStarted() {}
+    virtual void onAnimationUpdated(float fraction) = 0;
+    virtual void onAnimationFinished() {}
+
+private:
+    void callOnFinishedListener(TreeInfo& info);
+
+    enum PlayState {
+        PENDING,
+        RUNNING,
+        FINISHED,
+    };
+
+    Interpolator* mInterpolator;
+    PlayState mPlayState;
+    long mStartTime;
+    long mDuration;
+
+   sp<AnimationListener> mListener;
+};
+
+class BaseRenderNodeAnimator : public BaseAnimator {
 public:
     // Since the UI thread doesn't necessarily know what the current values
     // actually are and thus can't do the calculations, this is used to inform
@@ -43,6 +97,29 @@
         DELTA,
     };
 
+    bool animate(RenderNode* target, TreeInfo& info);
+
+protected:
+    BaseRenderNodeAnimator(DeltaValueType deltaType, float deltaValue);
+
+    RenderNode* target() const { return mTarget; }
+    virtual float getValue() const = 0;
+    virtual void setValue(float value) = 0;
+
+private:
+    virtual void onAnimationStarted();
+    virtual void onAnimationUpdated(float fraction);
+
+    // mTarget is only valid inside animate()
+    RenderNode* mTarget;
+
+    BaseRenderNodeAnimator::DeltaValueType mDeltaValueType;
+    float mDeltaValue;
+    float mFromValue;
+};
+
+class RenderPropertyAnimator : public BaseRenderNodeAnimator {
+public:
     enum RenderProperty {
         TRANSLATION_X = 0,
         TRANSLATION_Y,
@@ -58,19 +135,53 @@
         ALPHA,
     };
 
-    ANDROID_API void setInterpolator(Interpolator* interpolator);
-    ANDROID_API void setDuration(nsecs_t durationInMs);
-    ANDROID_API bool isFinished();
-
-    bool animate(RenderProperties* target, TreeInfo& info);
+    ANDROID_API RenderPropertyAnimator(RenderProperty property,
+                DeltaValueType deltaType, float deltaValue);
 
 protected:
-    ANDROID_API RenderPropertyAnimator(RenderProperty property, DeltaValueType deltaType,
-            float deltaValue);
-    ANDROID_API virtual ~RenderPropertyAnimator();
+    ANDROID_API virtual float getValue() const;
+    ANDROID_API virtual void setValue(float value);
 
 private:
-    RenderPropertyAnimatorImpl* mImpl;
+    typedef void (RenderProperties::*SetFloatProperty)(float value);
+    typedef float (RenderProperties::*GetFloatProperty)() const;
+
+    struct PropertyAccessors {
+        GetFloatProperty getter;
+        SetFloatProperty setter;
+    };
+
+    PropertyAccessors mPropertyAccess;
+
+    static const PropertyAccessors PROPERTY_ACCESSOR_LUT[];
+};
+
+class CanvasPropertyPrimitiveAnimator : public BaseRenderNodeAnimator {
+public:
+    ANDROID_API CanvasPropertyPrimitiveAnimator(CanvasPropertyPrimitive* property,
+            DeltaValueType deltaType, float deltaValue);
+protected:
+    ANDROID_API virtual float getValue() const;
+    ANDROID_API virtual void setValue(float value);
+private:
+    sp<CanvasPropertyPrimitive> mProperty;
+};
+
+class CanvasPropertyPaintAnimator : public BaseRenderNodeAnimator {
+public:
+    enum PaintField {
+        STROKE_WIDTH = 0,
+        ALPHA,
+    };
+
+    ANDROID_API CanvasPropertyPaintAnimator(CanvasPropertyPaint* property,
+            PaintField field, DeltaValueType deltaType, float deltaValue);
+protected:
+    ANDROID_API virtual float getValue() const;
+    ANDROID_API virtual void setValue(float value);
+private:
+    sp<CanvasPropertyPaint> mProperty;
+    PaintField mField;
 };
 
 } /* namespace uirenderer */
diff --git a/libs/hwui/CanvasProperty.h b/libs/hwui/CanvasProperty.h
new file mode 100644
index 0000000..2e1d176
--- /dev/null
+++ b/libs/hwui/CanvasProperty.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef CANVASPROPERTY_H
+#define CANVASPROPERTY_H
+
+#include "utils/Macros.h"
+#include "utils/VirtualLightRefBase.h"
+
+#include <SkPaint.h>
+
+namespace android {
+namespace uirenderer {
+
+class CanvasPropertyPrimitive : public VirtualLightRefBase {
+    PREVENT_COPY_AND_ASSIGN(CanvasPropertyPrimitive);
+public:
+    CanvasPropertyPrimitive(float initialValue) : value(initialValue) {}
+
+    float value;
+};
+
+class CanvasPropertyPaint : public VirtualLightRefBase {
+    PREVENT_COPY_AND_ASSIGN(CanvasPropertyPaint);
+public:
+    CanvasPropertyPaint(const SkPaint& initialValue) : value(initialValue) {}
+
+    SkPaint value;
+};
+
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif /* CANVASPROPERTY_H */
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index fe70d13..eaeb772 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -140,6 +140,14 @@
     void addChild(DrawDisplayListOp* childOp);
     const Vector<DrawDisplayListOp*>& children() { return mChildren; }
 
+    void refProperty(CanvasPropertyPrimitive* prop) {
+        mReferenceHolders.push(prop);
+    }
+
+    void refProperty(CanvasPropertyPaint* prop) {
+        mReferenceHolders.push(prop);
+    }
+
 private:
     Vector< sp<VirtualLightRefBase> > mReferenceHolders;
 
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 6dfb918..ce92beb 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -1198,6 +1198,27 @@
     float mRadius;
 };
 
+class DrawCirclePropsOp : public DrawOp {
+public:
+    DrawCirclePropsOp(float* x, float* y, float* radius, const SkPaint* paint)
+            : DrawOp(paint), mX(x), mY(y), mRadius(radius) {}
+
+    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
+        return renderer.drawCircle(*mX, *mY, *mRadius, getPaint(renderer));
+    }
+
+    virtual void output(int level, uint32_t logFlags) const {
+        OP_LOG("Draw Circle Props x %p, y %p, r %p", mX, mY, mRadius);
+    }
+
+    virtual const char* name() { return "DrawCircleProps"; }
+
+private:
+    float* mX;
+    float* mY;
+    float* mRadius;
+};
+
 class DrawOvalOp : public DrawStrokableOp {
 public:
     DrawOvalOp(float left, float top, float right, float bottom, const SkPaint* paint)
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index e36d975..8afd106 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -299,6 +299,17 @@
     return DrawGlInfo::kStatusDone;
 }
 
+status_t DisplayListRenderer::drawCircle(CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y,
+        CanvasPropertyPrimitive* radius, CanvasPropertyPaint* paint) {
+    mDisplayListData->refProperty(x);
+    mDisplayListData->refProperty(y);
+    mDisplayListData->refProperty(radius);
+    mDisplayListData->refProperty(paint);
+    addDrawOp(new (alloc()) DrawCirclePropsOp(&x->value, &y->value,
+            &radius->value, &paint->value));
+    return DrawGlInfo::kStatusDone;
+}
+
 status_t DisplayListRenderer::drawOval(float left, float top, float right, float bottom,
         const SkPaint* paint) {
     paint = refPaint(paint);
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 04c5a73..25e78c1 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -135,6 +135,8 @@
     virtual status_t drawRoundRect(float left, float top, float right, float bottom,
             float rx, float ry, const SkPaint* paint);
     virtual status_t drawCircle(float x, float y, float radius, const SkPaint* paint);
+    virtual status_t drawCircle(CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y,
+                CanvasPropertyPrimitive* radius, CanvasPropertyPaint* paint);
     virtual status_t drawOval(float left, float top, float right, float bottom,
             const SkPaint* paint);
     virtual status_t drawArc(float left, float top, float right, float bottom,
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index b49d1e1..7794abc 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -49,6 +49,7 @@
 #include "UvMapper.h"
 #include "Vertex.h"
 #include "Caches.h"
+#include "CanvasProperty.h"
 
 namespace android {
 namespace uirenderer {
@@ -200,6 +201,12 @@
     virtual status_t drawRoundRect(float left, float top, float right, float bottom,
             float rx, float ry, const SkPaint* paint);
     virtual status_t drawCircle(float x, float y, float radius, const SkPaint* paint);
+    virtual status_t drawCircle(CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y,
+            CanvasPropertyPrimitive* radius, CanvasPropertyPaint* paint) {
+        // TODO: Remove once android_view_GLES20Canvas uses DisplayListRenderer
+        // directly
+        return drawCircle(x->value, y->value, radius->value, &paint->value);
+    }
     virtual status_t drawOval(float left, float top, float right, float bottom,
             const SkPaint* paint);
     virtual status_t drawArc(float left, float top, float right, float bottom,
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 7a9c181..2c29985 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -109,7 +109,7 @@
     prepareSubTree(info, mDisplayListData);
 }
 
-static bool is_finished(const sp<RenderPropertyAnimator>& animator) {
+static bool is_finished(const sp<BaseRenderNodeAnimator>& animator) {
     return animator->isFinished();
 }
 
@@ -120,7 +120,7 @@
     }
     if (mNeedsAnimatorsSync) {
         mAnimators.resize(mStagingAnimators.size());
-        std::vector< sp<RenderPropertyAnimator> >::iterator it;
+        std::vector< sp<BaseRenderNodeAnimator> >::iterator it;
         // hint: this means copy_if_not()
         it = std::remove_copy_if(mStagingAnimators.begin(), mStagingAnimators.end(),
                 mAnimators.begin(), is_finished);
@@ -141,26 +141,22 @@
 
 class AnimateFunctor {
 public:
-    AnimateFunctor(RenderProperties* target, TreeInfo& info)
+    AnimateFunctor(RenderNode* 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;
+    bool operator() (sp<BaseRenderNodeAnimator>& animator) {
+        return animator->animate(mTarget, mInfo);
     }
 private:
-    RenderProperties* mTarget;
+    RenderNode* mTarget;
     TreeInfo& mInfo;
 };
 
 void RenderNode::evaluateAnimations(TreeInfo& info) {
     if (!mAnimators.size()) return;
 
-    AnimateFunctor functor(&mProperties, info);
-    std::vector< sp<RenderPropertyAnimator> >::iterator newEnd;
+    AnimateFunctor functor(this, info);
+    std::vector< sp<BaseRenderNodeAnimator> >::iterator newEnd;
     newEnd = std::remove_if(mAnimators.begin(), mAnimators.end(), functor);
     mAnimators.erase(newEnd, mAnimators.end());
     mProperties.updateMatrix();
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index 294f436..159903c 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -128,6 +128,10 @@
         return mProperties;
     }
 
+    RenderProperties& animatorProperties() {
+        return mProperties;
+    }
+
     const RenderProperties& stagingProperties() {
         return mStagingProperties;
     }
@@ -148,13 +152,13 @@
     ANDROID_API virtual void prepareTree(TreeInfo& info);
 
     // UI thread only!
-    ANDROID_API void addAnimator(const sp<RenderPropertyAnimator>& animator) {
+    ANDROID_API void addAnimator(const sp<BaseRenderNodeAnimator>& animator) {
         mStagingAnimators.insert(animator);
         mNeedsAnimatorsSync = true;
     }
 
     // UI thread only!
-    ANDROID_API void removeAnimator(const sp<RenderPropertyAnimator>& animator) {
+    ANDROID_API void removeAnimator(const sp<BaseRenderNodeAnimator>& animator) {
         mStagingAnimators.erase(animator);
         mNeedsAnimatorsSync = true;
     }
@@ -233,8 +237,8 @@
     DisplayListData* mStagingDisplayListData;
 
     bool mNeedsAnimatorsSync;
-    std::set< sp<RenderPropertyAnimator> > mStagingAnimators;
-    std::vector< sp<RenderPropertyAnimator> > mAnimators;
+    std::set< sp<BaseRenderNodeAnimator> > mStagingAnimators;
+    std::vector< sp<BaseRenderNodeAnimator> > mAnimators;
 
     /**
      * Draw time state - these properties are only set and used during rendering
diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h
index 8957607..a383fbf 100644
--- a/libs/hwui/TreeInfo.h
+++ b/libs/hwui/TreeInfo.h
@@ -16,20 +16,19 @@
 #ifndef TREEINFO_H
 #define TREEINFO_H
 
-#include <cutils/compiler.h>
 #include <utils/Timers.h>
-#include <utils/StrongPointer.h>
 
 namespace android {
 namespace uirenderer {
 
-class RenderPropertyAnimator;
+class BaseAnimator;
+class AnimationListener;
 
-class AnimationListener {
+class AnimationHook {
 public:
-    ANDROID_API virtual void onAnimationFinished(const sp<RenderPropertyAnimator>&) = 0;
+    virtual void callOnFinished(BaseAnimator* animator, AnimationListener* listener) = 0;
 protected:
-    ANDROID_API virtual ~AnimationListener() {}
+    ~AnimationHook() {}
 };
 
 struct TreeInfo {
@@ -41,7 +40,7 @@
             , frameTimeMs(0)
             , evaluateAnimations(false)
             , hasAnimations(false)
-            , animationListener(0)
+            , animationHook(0)
     {}
 
     bool hasFunctors;
@@ -53,7 +52,7 @@
     bool evaluateAnimations;
     // This is only updated if evaluateAnimations is true
     bool hasAnimations;
-    AnimationListener* animationListener;
+    AnimationHook* animationHook;
 
     // TODO: Damage calculations
 };
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index ff4be71..45f5cb0 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -112,6 +112,10 @@
     initTreeInfo(info);
     mContext->processLayerUpdates(&mLayers, info);
     mContext->prepareTree(info);
+    if (info.hasAnimations) {
+        // TODO: dirty calculations, for now just do a full-screen inval
+        mDirty.setEmpty();
+    }
     // If prepareTextures is false, we ran out of texture cache space
     return !info.hasFunctors && info.prepareTextures;
 }
diff --git a/libs/hwui/utils/Macros.h b/libs/hwui/utils/Macros.h
new file mode 100644
index 0000000..14a3ec0
--- /dev/null
+++ b/libs/hwui/utils/Macros.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef MACROS_H
+#define MACROS_H
+
+#define PREVENT_COPY_AND_ASSIGN(Type) \
+    private: \
+        Type(const Type&); \
+        void operator=(const Type&)
+
+
+#endif /* MACROS_H */