Support repeatMode = reverse in AVD

BUG: 30641232
Change-Id: I34c823a0a45c8441873a9b467275174c5529994b
diff --git a/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp b/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp
index 47252ad..ade718b 100644
--- a/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp
+++ b/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp
@@ -83,11 +83,13 @@
 }
 
 static void addAnimator(JNIEnv*, jobject, jlong animatorSetPtr, jlong propertyHolderPtr,
-        jlong interpolatorPtr, jlong startDelay, jlong duration, jint repeatCount) {
+        jlong interpolatorPtr, jlong startDelay, jlong duration, jint repeatCount,
+        jint repeatMode) {
     PropertyValuesAnimatorSet* set = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorSetPtr);
     PropertyValuesHolder* holder = reinterpret_cast<PropertyValuesHolder*>(propertyHolderPtr);
     Interpolator* interpolator = reinterpret_cast<Interpolator*>(interpolatorPtr);
-    set->addPropertyAnimator(holder, interpolator, startDelay, duration, repeatCount);
+    RepeatMode mode = static_cast<RepeatMode>(repeatMode);
+    set->addPropertyAnimator(holder, interpolator, startDelay, duration, repeatCount, mode);
 }
 
 static jlong createAnimatorSet(JNIEnv*, jobject) {
@@ -185,7 +187,7 @@
 static const JNINativeMethod gMethods[] = {
     {"nCreateAnimatorSet", "()J", (void*)createAnimatorSet},
     {"nSetVectorDrawableTarget", "(JJ)V", (void*)setVectorDrawableTarget},
-    {"nAddAnimator", "(JJJJJI)V", (void*)addAnimator},
+    {"nAddAnimator", "(JJJJJII)V", (void*)addAnimator},
     {"nCreateGroupPropertyHolder", "!(JIFF)J", (void*)createGroupPropertyHolder},
     {"nCreatePathDataPropertyHolder", "!(JJJ)J", (void*)createPathDataPropertyHolder},
     {"nCreatePathColorPropertyHolder", "!(JIII)J", (void*)createPathColorPropertyHolder},
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index 0bdc76f..87c472e 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -1358,7 +1358,7 @@
 
             mStartDelays.add(startDelay);
             nAddAnimator(mSetPtr, propertyPtr, nativeInterpolator, startDelay, duration,
-                    repeatCount);
+                    repeatCount, animator.getRepeatMode());
         }
 
         /**
@@ -1625,7 +1625,8 @@
     private static native long nCreateAnimatorSet();
     private static native void nSetVectorDrawableTarget(long animatorPtr, long vectorDrawablePtr);
     private static native void nAddAnimator(long setPtr, long propertyValuesHolder,
-             long nativeInterpolator, long startDelay, long duration, int repeatCount);
+            long nativeInterpolator, long startDelay, long duration, int repeatCount,
+            int repeatMode);
 
     private static native long nCreateGroupPropertyHolder(long nativePtr, int propertyId,
             float startValue, float endValue);
diff --git a/libs/hwui/Animator.h b/libs/hwui/Animator.h
index 9476750..259f21b 100644
--- a/libs/hwui/Animator.h
+++ b/libs/hwui/Animator.h
@@ -44,6 +44,12 @@
     ANDROID_API virtual ~AnimationListener() {}
 };
 
+enum class RepeatMode {
+    // These are the same values as the RESTART and REVERSE in ValueAnimator.java.
+    Restart = 1,
+    Reverse = 2
+};
+
 class BaseRenderNodeAnimator : public VirtualLightRefBase {
     PREVENT_COPY_AND_ASSIGN(BaseRenderNodeAnimator);
 public:
diff --git a/libs/hwui/PropertyValuesAnimatorSet.cpp b/libs/hwui/PropertyValuesAnimatorSet.cpp
index 796c73b..961132e 100644
--- a/libs/hwui/PropertyValuesAnimatorSet.cpp
+++ b/libs/hwui/PropertyValuesAnimatorSet.cpp
@@ -23,11 +23,11 @@
 namespace uirenderer {
 
 void PropertyValuesAnimatorSet::addPropertyAnimator(PropertyValuesHolder* propertyValuesHolder,
-            Interpolator* interpolator, nsecs_t startDelay,
-            nsecs_t duration, int repeatCount) {
+        Interpolator* interpolator, nsecs_t startDelay, nsecs_t duration, int repeatCount,
+        RepeatMode repeatMode) {
 
     PropertyAnimator* animator = new PropertyAnimator(propertyValuesHolder,
-            interpolator, startDelay, duration, repeatCount);
+            interpolator, startDelay, duration, repeatCount, repeatMode);
     mAnimators.emplace_back(animator);
 
     // Check whether any child animator is infinite after adding it them to the set.
@@ -66,14 +66,9 @@
             // Note that this set may containing animators modifying the same property, so when we
             // reset the animators, we need to make sure the animators that end the first will
             // have the final say on what the property value should be.
-            (*it)->setFraction(0);
+            (*it)->setFraction(0, 0);
         }
-    } else if (playTime >= mDuration) {
-        // Skip all the animators to end
-        for (auto& anim : mAnimators) {
-            anim->setFraction(1);
-        }
-    } else {
+    } else  {
         for (auto& anim : mAnimators) {
             anim->setCurrentPlayTime(playTime);
         }
@@ -124,7 +119,8 @@
 }
 
 PropertyAnimator::PropertyAnimator(PropertyValuesHolder* holder, Interpolator* interpolator,
-        nsecs_t startDelay, nsecs_t duration, int repeatCount)
+        nsecs_t startDelay, nsecs_t duration, int repeatCount,
+        RepeatMode repeatMode)
         : mPropertyValuesHolder(holder), mInterpolator(interpolator), mStartDelay(startDelay),
           mDuration(duration) {
     if (repeatCount < 0) {
@@ -132,24 +128,44 @@
     } else {
         mRepeatCount = repeatCount;
     }
+    mRepeatMode = repeatMode;
     mTotalDuration = ((nsecs_t) mRepeatCount + 1) * mDuration + mStartDelay;
 }
 
 void PropertyAnimator::setCurrentPlayTime(nsecs_t playTime) {
-    if (playTime >= mStartDelay && playTime < mTotalDuration) {
-         nsecs_t currentIterationPlayTime = (playTime - mStartDelay) % mDuration;
-         float fraction = currentIterationPlayTime / (float) mDuration;
-         setFraction(fraction);
-    } else if (mLatestFraction < 1.0f && playTime >= mTotalDuration) {
-        // This makes sure we only set the fraction = 1 once. It is needed because there might
-        // be another animator modifying the same property after this animator finishes, we need
-        // to make sure we don't set conflicting values on the same property within one frame.
-        setFraction(1.0f);
+    if (playTime < mStartDelay) {
+        return;
     }
+
+    float currentIterationFraction;
+    long iteration;
+    if (playTime >= mTotalDuration) {
+        // Reached the end of the animation.
+        iteration = mRepeatCount;
+        currentIterationFraction = 1.0f;
+    } else {
+        // play time here is in range [mStartDelay, mTotalDuration)
+        iteration = (playTime - mStartDelay) / mDuration;
+        currentIterationFraction = ((playTime - mStartDelay) % mDuration) / (float) mDuration;
+    }
+    setFraction(currentIterationFraction, iteration);
 }
 
-void PropertyAnimator::setFraction(float fraction) {
-    mLatestFraction = fraction;
+void PropertyAnimator::setFraction(float fraction, long iteration) {
+    double totalFraction = fraction + iteration;
+    // This makes sure we only set the fraction = repeatCount + 1 once. It is needed because there
+    // might be another animator modifying the same property after this animator finishes, we need
+    // to make sure we don't set conflicting values on the same property within one frame.
+    if ((mLatestFraction == mRepeatCount + 1) && (totalFraction >= mRepeatCount + 1)) {
+        return;
+    }
+
+    mLatestFraction = totalFraction;
+    // Check the play direction (i.e. reverse or restart) every other iteration, and calculate the
+    // fraction based on the play direction.
+    if (iteration % 2 && mRepeatMode == RepeatMode::Reverse) {
+        fraction = 1.0f - fraction;
+    }
     float interpolatedFraction = mInterpolator->interpolate(fraction);
     mPropertyValuesHolder->setFraction(interpolatedFraction);
 }
diff --git a/libs/hwui/PropertyValuesAnimatorSet.h b/libs/hwui/PropertyValuesAnimatorSet.h
index f9274e1..e208b08 100644
--- a/libs/hwui/PropertyValuesAnimatorSet.h
+++ b/libs/hwui/PropertyValuesAnimatorSet.h
@@ -26,12 +26,13 @@
 class PropertyAnimator {
 public:
     PropertyAnimator(PropertyValuesHolder* holder, Interpolator* interpolator, nsecs_t startDelay,
-            nsecs_t duration, int repeatCount);
+            nsecs_t duration, int repeatCount, RepeatMode repeatMode);
     void setCurrentPlayTime(nsecs_t playTime);
     nsecs_t getTotalDuration() {
         return mTotalDuration;
     }
-    void setFraction(float fraction);
+    // fraction range: [0, 1], iteration range [0, repeatCount]
+    void setFraction(float fraction, long iteration);
 
 private:
     std::unique_ptr<PropertyValuesHolder> mPropertyValuesHolder;
@@ -40,7 +41,8 @@
     nsecs_t mDuration;
     uint32_t mRepeatCount;
     nsecs_t mTotalDuration;
-    float mLatestFraction = 0.0f;
+    RepeatMode mRepeatMode;
+    double mLatestFraction = 0;
 };
 
 // TODO: This class should really be named VectorDrawableAnimator
@@ -56,7 +58,7 @@
 
     void addPropertyAnimator(PropertyValuesHolder* propertyValuesHolder,
             Interpolator* interpolators, int64_t startDelays,
-            nsecs_t durations, int repeatCount);
+            nsecs_t durations, int repeatCount, RepeatMode repeatMode);
     virtual uint32_t dirtyMask();
     bool isInfinite() { return mIsInfinite; }
     void setVectorDrawable(VectorDrawableRoot* vd) { mVectorDrawable = vd; }