Animator refactoring & fixes

 Tweaks animators to have less unnecessary refcounting

 Pull animator management out into seperate class

 More control to tweak animator lifecycle, such as doing
 Java-side handling of start delay by attaching but not
 starting the animator

Change-Id: I4ff8207580ca11fb38f45ef0007b406e0097281c
diff --git a/libs/hwui/Animator.cpp b/libs/hwui/Animator.cpp
index dc6d852..4a8c122 100644
--- a/libs/hwui/Animator.cpp
+++ b/libs/hwui/Animator.cpp
@@ -18,6 +18,7 @@
 
 #include "Animator.h"
 
+#include <inttypes.h>
 #include <set>
 
 #include "RenderNode.h"
@@ -35,72 +36,105 @@
         , mDeltaValue(0)
         , mFromValue(0)
         , mInterpolator(0)
-        , mPlayState(NEEDS_START)
+        , mStagingPlayState(NOT_STARTED)
+        , mPlayState(NOT_STARTED)
+        , mHasStartValue(false)
         , mStartTime(0)
-        , mDelayUntil(0)
         , mDuration(300)
         , mStartDelay(0) {
-
 }
 
 BaseRenderNodeAnimator::~BaseRenderNodeAnimator() {
-    setInterpolator(NULL);
+    delete mInterpolator;
+}
+
+void BaseRenderNodeAnimator::checkMutable() {
+    // Should be impossible to hit as the Java-side also has guards for this
+    LOG_ALWAYS_FATAL_IF(mStagingPlayState != NOT_STARTED,
+            "Animator has already been started!");
 }
 
 void BaseRenderNodeAnimator::setInterpolator(Interpolator* interpolator) {
+    checkMutable();
     delete mInterpolator;
     mInterpolator = interpolator;
 }
 
 void BaseRenderNodeAnimator::setStartValue(float value) {
-    LOG_ALWAYS_FATAL_IF(mPlayState != NEEDS_START,
-            "Cannot set the start value after the animator has started!");
-    mFromValue = value;
-    mDeltaValue = (mFinalValue - mFromValue);
-    mPlayState = PENDING;
+    checkMutable();
+    doSetStartValue(value);
 }
 
-void BaseRenderNodeAnimator::setupStartValueIfNecessary(RenderNode* target, TreeInfo& info) {
-    if (mPlayState == NEEDS_START) {
-        setStartValue(getValue(target));
-    }
+void BaseRenderNodeAnimator::doSetStartValue(float value) {
+    mFromValue = value;
+    mDeltaValue = (mFinalValue - mFromValue);
+    mHasStartValue = true;
 }
 
 void BaseRenderNodeAnimator::setDuration(nsecs_t duration) {
+    checkMutable();
     mDuration = duration;
 }
 
 void BaseRenderNodeAnimator::setStartDelay(nsecs_t startDelay) {
+    checkMutable();
     mStartDelay = startDelay;
 }
 
-bool BaseRenderNodeAnimator::animate(RenderNode* target, TreeInfo& info) {
-    if (mPlayState == PENDING && mStartDelay > 0 && mDelayUntil == 0) {
-        mDelayUntil = info.frameTimeMs + mStartDelay;
-        return false;
+void BaseRenderNodeAnimator::pushStaging(RenderNode* target, TreeInfo& info) {
+    if (!mHasStartValue) {
+        doSetStartValue(getValue(target));
     }
-
-    if (mDelayUntil > info.frameTimeMs) {
-        return false;
-    }
-
-    if (mPlayState == PENDING) {
-        mPlayState = RUNNING;
-        mStartTime = info.frameTimeMs;
-        // No interpolator was set, use the default
-        if (!mInterpolator) {
-            setInterpolator(Interpolator::createDefaultInterpolator());
+    if (mStagingPlayState > mPlayState) {
+        mPlayState = mStagingPlayState;
+        // Oh boy, we're starting! Man the battle stations!
+        if (mPlayState == RUNNING) {
+            transitionToRunning(info);
         }
     }
+}
+
+void BaseRenderNodeAnimator::transitionToRunning(TreeInfo& info) {
+    LOG_ALWAYS_FATAL_IF(info.frameTimeMs <= 0, "%" PRId64 " isn't a real frame time!", info.frameTimeMs);
+    if (mStartDelay < 0 || mStartDelay > 50000) {
+        ALOGW("Your start delay is strange and confusing: %" PRId64, mStartDelay);
+    }
+    mStartTime = info.frameTimeMs + mStartDelay;
+    if (mStartTime < 0) {
+        ALOGW("Ended up with a really weird start time of %" PRId64
+                " with frame time %" PRId64 " and start delay %" PRId64,
+                mStartTime, info.frameTimeMs, mStartDelay);
+        // Set to 0 so that the animate() basically instantly finishes
+        mStartTime = 0;
+    }
+    // No interpolator was set, use the default
+    if (!mInterpolator) {
+        setInterpolator(Interpolator::createDefaultInterpolator());
+    }
+    if (mDuration < 0 || mDuration > 50000) {
+        ALOGW("Your duration is strange and confusing: %" PRId64, mDuration);
+    }
+}
+
+bool BaseRenderNodeAnimator::animate(RenderNode* target, TreeInfo& info) {
+    if (mPlayState < RUNNING) {
+        return false;
+    }
+
+    if (mStartTime > info.frameTimeMs) {
+        info.out.hasAnimations |= true;
+        return false;
+    }
 
     float fraction = 1.0f;
-    if (mPlayState == RUNNING) {
-        fraction = mDuration > 0 ? (float)(info.frameTimeMs - mStartTime) / mDuration : 1.0f;
-        if (fraction >= 1.0f) {
-            fraction = 1.0f;
-            mPlayState = FINISHED;
-        }
+    if (mPlayState == RUNNING && mDuration > 0) {
+        fraction = (float)(info.frameTimeMs - mStartTime) / mDuration;
     }
+    if (fraction >= 1.0f) {
+        fraction = 1.0f;
+        mPlayState = FINISHED;
+    }
+
     fraction = mInterpolator->interpolate(fraction);
     setValue(target, mFromValue + (mDeltaValue * fraction));
 
@@ -108,6 +142,8 @@
         callOnFinishedListener(info);
         return true;
     }
+
+    info.out.hasAnimations |= true;
     return false;
 }
 
@@ -153,7 +189,7 @@
 }
 
 void RenderPropertyAnimator::onAttached(RenderNode* target) {
-    if (mPlayState == NEEDS_START
+    if (!mHasStartValue
             && target->isPropertyFieldDirty(mPropertyAccess->dirtyMask)) {
         setStartValue((target->stagingProperties().*mPropertyAccess->getter)());
     }