RenderThread animator support

Change-Id: Icf29098edfdaf7ed550bbe9d49e9eaefb4167084
diff --git a/libs/hwui/Animator.cpp b/libs/hwui/Animator.cpp
new file mode 100644
index 0000000..ee16586
--- /dev/null
+++ b/libs/hwui/Animator.cpp
@@ -0,0 +1,240 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "RT-Animator"
+
+#include "Animator.h"
+
+#include <set>
+
+#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
+ ************************************************************/
+
+BaseAnimator::BaseAnimator()
+        : mInterpolator(0)
+        , mPlayState(PENDING)
+        , mStartTime(0)
+        , mDuration(300) {
+
+}
+
+BaseAnimator::~BaseAnimator() {
+    setInterpolator(NULL);
+}
+
+void BaseAnimator::setInterpolator(Interpolator* interpolator) {
+    delete mInterpolator;
+    mInterpolator = interpolator;
+}
+
+void BaseAnimator::setDuration(nsecs_t duration) {
+    mDuration = duration;
+}
+
+bool BaseAnimator::animateFrame(nsecs_t frameTime) {
+    if (mPlayState == PENDING) {
+        mPlayState = RUNNING;
+        mStartTime = frameTime;
+        // No interpolator was set, use the default
+        if (!mInterpolator) {
+            setInterpolator(Interpolator::createDefaultInterpolator());
+        }
+        onAnimationStarted();
+    }
+
+    float fraction = 1.0f;
+    if (mPlayState == RUNNING) {
+        fraction = mDuration > 0 ? (float)(frameTime - mStartTime) / mDuration : 1.0f;
+        if (fraction >= 1.0f) {
+            fraction = 1.0f;
+            mPlayState = FINISHED;
+        }
+    }
+    fraction = mInterpolator->interpolate(fraction);
+    onAnimationUpdated(fraction);
+
+    if (mPlayState == FINISHED) {
+        onAnimationFinished();
+        return true;
+    }
+    return false;
+}
+
+/************************************************************
+ *  RenderPropertyAnimator
+ ************************************************************/
+
+RenderPropertyAnimatorImpl::RenderPropertyAnimatorImpl(
+                GetFloatProperty getter, SetFloatProperty setter,
+                RenderPropertyAnimator::DeltaValueType deltaType, float delta)
+        : mTarget(0)
+        , mGetter(getter)
+        , mSetter(setter)
+        , mDeltaValueType(deltaType)
+        , mDeltaValue(delta)
+        , mFromValue(-1) {
+}
+
+RenderPropertyAnimatorImpl::~RenderPropertyAnimatorImpl() {
+}
+
+bool RenderPropertyAnimatorImpl::animate(RenderProperties* target, TreeInfo& info) {
+    mTarget = target;
+    bool finished = animateFrame(info.frameTimeMs);
+    mTarget = NULL;
+    return finished;
+}
+
+void RenderPropertyAnimatorImpl::onAnimationStarted() {
+    mFromValue = (mTarget->*mGetter)();
+
+    if (mDeltaValueType == RenderPropertyAnimator::ABSOLUTE) {
+        mDeltaValue = (mDeltaValue - mFromValue);
+        mDeltaValueType = RenderPropertyAnimator::DELTA;
+    }
+}
+
+void RenderPropertyAnimatorImpl::onAnimationUpdated(float fraction) {
+    float value = mFromValue + (mDeltaValue * fraction);
+    (mTarget->*mSetter)(value);
+}
+
+} /* namespace uirenderer */
+} /* namespace android */