public void end() {
   if (!sAnimations.get().contains(this) && !sPendingAnimations.get().contains(this)) {
     // Special case if the animation has not yet started; get it ready for ending
     mStartedDelay = false;
     startAnimation();
   } else if (!mInitialized) {
     initAnimation();
   }
   // The final value set on the target varies, depending on whether the animation
   // was supposed to repeat an odd number of times
   if (mRepeatCount > 0 && (mRepeatCount & 0x01) == 1) {
     animateValue(0f);
   } else {
     animateValue(1f);
   }
   endAnimation();
 }
  /**
   * This internal function processes a single animation frame for a given animation. The
   * currentTime parameter is the timing pulse sent by the handler, used to calculate the elapsed
   * duration, and therefore the elapsed fraction, of the animation. The return value indicates
   * whether the animation should be ended (which happens when the elapsed time of the animation
   * exceeds the animation's duration, including the repeatCount).
   *
   * @param currentTime The current time, as tracked by the static timing handler
   * @return true if the animation's duration, including any repetitions due to <code>repeatCount
   *     </code> has been exceeded and the animation should be ended.
   */
  boolean animationFrame(long currentTime) {
    boolean done = false;

    if (mPlayingState == STOPPED) {
      mPlayingState = RUNNING;
      if (mSeekTime < 0) {
        mStartTime = currentTime;
      } else {
        mStartTime = currentTime - mSeekTime;
        // Now that we're playing, reset the seek time
        mSeekTime = -1;
      }
    }
    switch (mPlayingState) {
      case RUNNING:
      case SEEKED:
        float fraction = mDuration > 0 ? (float) (currentTime - mStartTime) / mDuration : 1f;
        if (fraction >= 1f) {
          if (mCurrentIteration < mRepeatCount || mRepeatCount == INFINITE) {
            // Time to repeat
            if (mListeners != null) {
              int numListeners = mListeners.size();
              for (int i = 0; i < numListeners; ++i) {
                mListeners.get(i).onAnimationRepeat(this);
              }
            }
            if (mRepeatMode == REVERSE) {
              mPlayingBackwards = mPlayingBackwards ? false : true;
            }
            mCurrentIteration += (int) fraction;
            fraction = fraction % 1f;
            mStartTime += mDuration;
          } else {
            done = true;
            fraction = Math.min(fraction, 1.0f);
          }
        }
        if (mPlayingBackwards) {
          fraction = 1f - fraction;
        }
        animateValue(fraction);
        break;
    }

    return done;
  }