Support Keyframe definition for AVD on RT

BUG: 27441613
Change-Id: Iece386f65f3704d1b7caa2b3690a8d3048ccf6e2
diff --git a/libs/hwui/PropertyValuesHolder.cpp b/libs/hwui/PropertyValuesHolder.cpp
index 0932d65..6ba0ab5 100644
--- a/libs/hwui/PropertyValuesHolder.cpp
+++ b/libs/hwui/PropertyValuesHolder.cpp
@@ -25,7 +25,27 @@
 
 using namespace VectorDrawable;
 
-float PropertyValuesHolder::getValueFromData(float fraction) {
+inline U8CPU lerp(U8CPU fromValue, U8CPU toValue, float fraction) {
+    return (U8CPU) (fromValue * (1 - fraction) + toValue * fraction);
+}
+
+// TODO: Add a test for this
+void ColorEvaluator::evaluate(SkColor* outColor,
+        const SkColor& fromColor, const SkColor& toColor, float fraction) const {
+    U8CPU alpha = lerp(SkColorGetA(fromColor), SkColorGetA(toColor), fraction);
+    U8CPU red = lerp(SkColorGetR(fromColor), SkColorGetR(toColor), fraction);
+    U8CPU green = lerp(SkColorGetG(fromColor), SkColorGetG(toColor), fraction);
+    U8CPU blue = lerp(SkColorGetB(fromColor), SkColorGetB(toColor), fraction);
+    *outColor = SkColorSetARGB(alpha, red, green, blue);
+}
+
+void PathEvaluator::evaluate(PathData* out,
+        const PathData& from, const PathData& to, float fraction) const {
+    VectorDrawableUtils::interpolatePaths(out, from, to, fraction);
+}
+
+template<typename T>
+const T PropertyValuesHolderImpl<T>::getValueFromData(float fraction) const {
     if (mDataSource.size() == 0) {
         LOG_ALWAYS_FATAL("No data source is defined");
         return 0;
@@ -41,57 +61,44 @@
     int lowIndex = floor(fraction);
     fraction -= lowIndex;
 
-    float value = mDataSource[lowIndex] * (1.0f - fraction)
-            + mDataSource[lowIndex + 1] * fraction;
+    T value;
+    mEvaluator->evaluate(&value, mDataSource[lowIndex], mDataSource[lowIndex + 1], fraction);
     return value;
 }
 
-void GroupPropertyValuesHolder::setFraction(float fraction) {
-    float animatedValue;
+template<typename T>
+const T PropertyValuesHolderImpl<T>::calculateAnimatedValue(float fraction) const {
     if (mDataSource.size() > 0) {
-        animatedValue = getValueFromData(fraction);
+        return getValueFromData(fraction);
     } else {
-        animatedValue = mStartValue * (1 - fraction) + mEndValue * fraction;
+        T value;
+        mEvaluator->evaluate(&value, mStartValue, mEndValue, fraction);
+        return value;
     }
+}
+
+void GroupPropertyValuesHolder::setFraction(float fraction) {
+    float animatedValue = calculateAnimatedValue(fraction);
     mGroup->mutateProperties()->setPropertyValue(mPropertyId, animatedValue);
 }
 
-inline U8CPU lerp(U8CPU fromValue, U8CPU toValue, float fraction) {
-    return (U8CPU) (fromValue * (1 - fraction) + toValue * fraction);
-}
-
-// TODO: Add a test for this
-SkColor FullPathColorPropertyValuesHolder::interpolateColors(SkColor fromColor, SkColor toColor,
-        float fraction) {
-    U8CPU alpha = lerp(SkColorGetA(fromColor), SkColorGetA(toColor), fraction);
-    U8CPU red = lerp(SkColorGetR(fromColor), SkColorGetR(toColor), fraction);
-    U8CPU green = lerp(SkColorGetG(fromColor), SkColorGetG(toColor), fraction);
-    U8CPU blue = lerp(SkColorGetB(fromColor), SkColorGetB(toColor), fraction);
-    return SkColorSetARGB(alpha, red, green, blue);
-}
-
 void FullPathColorPropertyValuesHolder::setFraction(float fraction) {
-    SkColor animatedValue = interpolateColors(mStartValue, mEndValue, fraction);
+    SkColor animatedValue = calculateAnimatedValue(fraction);
     mFullPath->mutateProperties()->setColorPropertyValue(mPropertyId, animatedValue);
 }
 
 void FullPathPropertyValuesHolder::setFraction(float fraction) {
-    float animatedValue;
-    if (mDataSource.size() > 0) {
-        animatedValue = getValueFromData(fraction);
-    } else {
-        animatedValue = mStartValue * (1 - fraction) + mEndValue * fraction;
-    }
+    float animatedValue = calculateAnimatedValue(fraction);
     mFullPath->mutateProperties()->setPropertyValue(mPropertyId, animatedValue);
 }
 
 void PathDataPropertyValuesHolder::setFraction(float fraction) {
-    VectorDrawableUtils::interpolatePaths(&mPathData, mStartValue, mEndValue, fraction);
+    mEvaluator->evaluate(&mPathData, mStartValue, mEndValue, fraction);
     mPath->mutateProperties()->setData(mPathData);
 }
 
 void RootAlphaPropertyValuesHolder::setFraction(float fraction) {
-    float animatedValue = mStartValue * (1 - fraction) + mEndValue * fraction;
+    float animatedValue = calculateAnimatedValue(fraction);
     mTree->mutateProperties()->setRootAlpha(animatedValue);
 }
 
diff --git a/libs/hwui/PropertyValuesHolder.h b/libs/hwui/PropertyValuesHolder.h
index b905fae..432f8ba 100644
--- a/libs/hwui/PropertyValuesHolder.h
+++ b/libs/hwui/PropertyValuesHolder.h
@@ -31,91 +31,130 @@
 class ANDROID_API PropertyValuesHolder {
 public:
     virtual void setFraction(float fraction) = 0;
-    void setPropertyDataSource(float* dataSource, int length) {
-        mDataSource.insert(mDataSource.begin(), dataSource, dataSource + length);
-    }
-   float getValueFromData(float fraction);
-   virtual ~PropertyValuesHolder() {}
-protected:
-   std::vector<float> mDataSource;
+    virtual ~PropertyValuesHolder() {}
 };
 
-class ANDROID_API GroupPropertyValuesHolder : public PropertyValuesHolder {
+template <typename T>
+class Evaluator {
+public:
+    virtual void evaluate(T* out, const T& from, const T& to, float fraction) const {};
+    virtual ~Evaluator() {}
+};
+
+class FloatEvaluator : public Evaluator<float> {
+public:
+    virtual void evaluate(float* out, const float& from, const float& to, float fraction)
+            const override {
+        *out = from * (1 - fraction) + to * fraction;
+    }
+};
+
+class ANDROID_API ColorEvaluator : public Evaluator<SkColor> {
+public:
+    virtual void evaluate(SkColor* outColor, const SkColor& from, const SkColor& to,
+            float fraction) const override;
+};
+
+class ANDROID_API PathEvaluator : public Evaluator<PathData> {
+    virtual void evaluate(PathData* out, const PathData& from, const PathData& to, float fraction)
+            const override;
+};
+
+template <typename T>
+class ANDROID_API PropertyValuesHolderImpl : public PropertyValuesHolder {
+public:
+    PropertyValuesHolderImpl(const T& startValue, const T& endValue)
+            : mStartValue(startValue)
+            , mEndValue(endValue) {}
+    void setPropertyDataSource(T* dataSource, int length) {
+        mDataSource.insert(mDataSource.begin(), dataSource, dataSource + length);
+    }
+    // Calculate the animated value from the data source.
+    const T getValueFromData(float fraction) const;
+    // Convenient method to favor getting animated value from data source. If no data source is set
+    // fall back to linear interpolation.
+    const T calculateAnimatedValue(float fraction) const;
+protected:
+   std::unique_ptr<Evaluator<T>> mEvaluator = nullptr;
+   // This contains uniformly sampled data throughout the animation duration. The first element
+   // should be the start value and the last should be the end value of the animation. When the
+   // data source is set, we'll favor data source over the linear interpolation of start/end value
+   // for calculation of animated value.
+   std::vector<T> mDataSource;
+   T mStartValue;
+   T mEndValue;
+};
+
+class ANDROID_API GroupPropertyValuesHolder : public PropertyValuesHolderImpl<float> {
 public:
     GroupPropertyValuesHolder(VectorDrawable::Group* ptr, int propertyId, float startValue,
             float endValue)
-            : mGroup(ptr)
-            , mPropertyId(propertyId)
-            , mStartValue(startValue)
-            , mEndValue(endValue){
+            : PropertyValuesHolderImpl(startValue, endValue)
+            , mGroup(ptr)
+            , mPropertyId(propertyId) {
+        mEvaluator.reset(new FloatEvaluator());
     }
     void setFraction(float fraction) override;
 private:
     VectorDrawable::Group* mGroup;
     int mPropertyId;
-    float mStartValue;
-    float mEndValue;
 };
 
-class ANDROID_API FullPathColorPropertyValuesHolder : public PropertyValuesHolder {
+class ANDROID_API FullPathColorPropertyValuesHolder : public PropertyValuesHolderImpl<SkColor> {
 public:
-    FullPathColorPropertyValuesHolder(VectorDrawable::FullPath* ptr, int propertyId, int32_t startValue,
-            int32_t endValue)
-            : mFullPath(ptr)
-            , mPropertyId(propertyId)
-            , mStartValue(startValue)
-            , mEndValue(endValue) {};
+    FullPathColorPropertyValuesHolder(VectorDrawable::FullPath* ptr, int propertyId,
+            SkColor startValue, SkColor endValue)
+            : PropertyValuesHolderImpl(startValue, endValue)
+            , mFullPath(ptr)
+            , mPropertyId(propertyId) {
+        mEvaluator.reset(new ColorEvaluator());
+    }
     void setFraction(float fraction) override;
     static SkColor interpolateColors(SkColor fromColor, SkColor toColor, float fraction);
 private:
     VectorDrawable::FullPath* mFullPath;
     int mPropertyId;
-    int32_t mStartValue;
-    int32_t mEndValue;
 };
 
-class ANDROID_API FullPathPropertyValuesHolder : public PropertyValuesHolder {
+class ANDROID_API FullPathPropertyValuesHolder : public PropertyValuesHolderImpl<float> {
 public:
     FullPathPropertyValuesHolder(VectorDrawable::FullPath* ptr, int propertyId, float startValue,
             float endValue)
-            : mFullPath(ptr)
-            , mPropertyId(propertyId)
-            , mStartValue(startValue)
-            , mEndValue(endValue) {};
+            : PropertyValuesHolderImpl(startValue, endValue)
+            , mFullPath(ptr)
+            , mPropertyId(propertyId) {
+        mEvaluator.reset(new FloatEvaluator());
+    };
     void setFraction(float fraction) override;
 private:
     VectorDrawable::FullPath* mFullPath;
     int mPropertyId;
-    float mStartValue;
-    float mEndValue;
 };
 
-class ANDROID_API PathDataPropertyValuesHolder : public PropertyValuesHolder {
+class ANDROID_API PathDataPropertyValuesHolder : public PropertyValuesHolderImpl<PathData> {
 public:
     PathDataPropertyValuesHolder(VectorDrawable::Path* ptr, PathData* startValue,
             PathData* endValue)
-            : mPath(ptr)
-            , mStartValue(*startValue)
-            , mEndValue(*endValue) {};
+            : PropertyValuesHolderImpl(*startValue, *endValue)
+            , mPath(ptr) {
+        mEvaluator.reset(new PathEvaluator());
+    };
     void setFraction(float fraction) override;
 private:
     VectorDrawable::Path* mPath;
     PathData mPathData;
-    PathData mStartValue;
-    PathData mEndValue;
 };
 
-class ANDROID_API RootAlphaPropertyValuesHolder : public PropertyValuesHolder {
+class ANDROID_API RootAlphaPropertyValuesHolder : public PropertyValuesHolderImpl<float> {
 public:
     RootAlphaPropertyValuesHolder(VectorDrawable::Tree* tree, float startValue, float endValue)
-            : mTree(tree)
-            , mStartValue(startValue)
-            , mEndValue(endValue) {}
+            : PropertyValuesHolderImpl(startValue, endValue)
+            , mTree(tree) {
+        mEvaluator.reset(new FloatEvaluator());
+    }
     void setFraction(float fraction) override;
 private:
     VectorDrawable::Tree* mTree;
-    float mStartValue;
-    float mEndValue;
 };
 }
 }