Merge "Animator start value..."
diff --git a/core/java/android/view/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java
index ec4d560..f14e73f 100644
--- a/core/java/android/view/RenderNodeAnimator.java
+++ b/core/java/android/view/RenderNodeAnimator.java
@@ -21,7 +21,6 @@
 import android.graphics.CanvasProperty;
 import android.graphics.Paint;
 import android.util.SparseIntArray;
-import android.util.TimeUtils;
 
 import com.android.internal.util.VirtualRefBasePtr;
 import com.android.internal.view.animation.FallbackLUTInterpolator;
@@ -72,10 +71,6 @@
         put(ViewPropertyAnimator.ALPHA, ALPHA);
     }};
 
-    // Keep in sync DeltaValueType in Animator.h
-    public static final int DELTA_TYPE_ABSOLUTE = 0;
-    public static final int DELTA_TYPE_DELTA = 1;
-
     private VirtualRefBasePtr mNativePtr;
 
     private RenderNode mTarget;
@@ -86,22 +81,21 @@
         return sViewPropertyAnimatorMap.get(viewProperty);
     }
 
-    public RenderNodeAnimator(int property, int deltaType, float deltaValue) {
+    public RenderNodeAnimator(int property, float finalValue) {
         init(nCreateAnimator(new WeakReference<RenderNodeAnimator>(this),
-                property, deltaType, deltaValue));
+                property, finalValue));
     }
 
-    public RenderNodeAnimator(CanvasProperty<Float> property, int deltaType, float deltaValue) {
+    public RenderNodeAnimator(CanvasProperty<Float> property, float finalValue) {
         init(nCreateCanvasPropertyFloatAnimator(
                 new WeakReference<RenderNodeAnimator>(this),
-                property.getNativeContainer(), deltaType, deltaValue));
+                property.getNativeContainer(), finalValue));
     }
 
-    public RenderNodeAnimator(CanvasProperty<Paint> property, int paintField,
-            int deltaType, float deltaValue) {
+    public RenderNodeAnimator(CanvasProperty<Paint> property, int paintField, float finalValue) {
         init(nCreateCanvasPropertyPaintAnimator(
                 new WeakReference<RenderNodeAnimator>(this),
-                property.getNativeContainer(), paintField, deltaType, deltaValue));
+                property.getNativeContainer(), paintField, finalValue));
     }
 
     private void init(long ptr) {
@@ -182,11 +176,11 @@
     }
 
     private static native long nCreateAnimator(WeakReference<RenderNodeAnimator> weakThis,
-            int property, int deltaValueType, float deltaValue);
+            int property, float deltaValue);
     private static native long nCreateCanvasPropertyFloatAnimator(WeakReference<RenderNodeAnimator> weakThis,
-            long canvasProperty, int deltaValueType, float deltaValue);
+            long canvasProperty, float deltaValue);
     private static native long nCreateCanvasPropertyPaintAnimator(WeakReference<RenderNodeAnimator> weakThis,
-            long canvasProperty, int paintField, int deltaValueType, float deltaValue);
+            long canvasProperty, int paintField, float deltaValue);
     private static native void nSetDuration(long nativePtr, int duration);
     private static native int nGetDuration(long nativePtr);
     private static native void nSetInterpolator(long animPtr, long interpolatorPtr);
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index e45a901..b0defdb 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -80,6 +80,7 @@
         jobject clazz, jlong renderNodePtr, jboolean caching) {
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
     renderNode->mutateStagingProperties().setCaching(caching);
+    renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
 }
 
 static void android_view_RenderNode_setStaticMatrix(JNIEnv* env,
@@ -87,6 +88,7 @@
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
     SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
     renderNode->mutateStagingProperties().setStaticMatrix(matrix);
+    renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
 }
 
 static void android_view_RenderNode_setAnimationMatrix(JNIEnv* env,
@@ -94,24 +96,28 @@
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
     SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
     renderNode->mutateStagingProperties().setAnimationMatrix(matrix);
+    renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
 }
 
 static void android_view_RenderNode_setClipToBounds(JNIEnv* env,
         jobject clazz, jlong renderNodePtr, jboolean clipToBounds) {
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
     renderNode->mutateStagingProperties().setClipToBounds(clipToBounds);
+    renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
 }
 
 static void android_view_RenderNode_setProjectBackwards(JNIEnv* env,
         jobject clazz, jlong renderNodePtr, jboolean shouldProject) {
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
     renderNode->mutateStagingProperties().setProjectBackwards(shouldProject);
+    renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
 }
 
 static void android_view_RenderNode_setProjectionReceiver(JNIEnv* env,
         jobject clazz, jlong renderNodePtr, jboolean shouldRecieve) {
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
     renderNode->mutateStagingProperties().setProjectionReceiver(shouldRecieve);
+    renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
 }
 
 static void android_view_RenderNode_setOutlineRoundRect(JNIEnv* env,
@@ -119,6 +125,7 @@
         jint right, jint bottom, jfloat radius) {
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
     renderNode->mutateStagingProperties().mutableOutline().setRoundRect(left, top, right, bottom, radius);
+    renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
 }
 
 static void android_view_RenderNode_setOutlineConvexPath(JNIEnv* env,
@@ -126,18 +133,21 @@
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
     SkPath* outlinePath = reinterpret_cast<SkPath*>(outlinePathPtr);
     renderNode->mutateStagingProperties().mutableOutline().setConvexPath(outlinePath);
+    renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
 }
 
 static void android_view_RenderNode_setOutlineEmpty(JNIEnv* env,
         jobject clazz, jlong renderNodePtr) {
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
     renderNode->mutateStagingProperties().mutableOutline().setEmpty();
+    renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
 }
 
 static void android_view_RenderNode_setClipToOutline(JNIEnv* env,
         jobject clazz, jlong renderNodePtr, jboolean clipToOutline) {
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
     renderNode->mutateStagingProperties().mutableOutline().setShouldClip(clipToOutline);
+    renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
 }
 
 static void android_view_RenderNode_setRevealClip(JNIEnv* env,
@@ -146,114 +156,133 @@
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
     renderNode->mutateStagingProperties().mutableRevealClip().set(
             shouldClip, inverseClip, x, y, radius);
+    renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
 }
 
 static void android_view_RenderNode_setAlpha(JNIEnv* env,
         jobject clazz, jlong renderNodePtr, float alpha) {
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
     renderNode->mutateStagingProperties().setAlpha(alpha);
+    renderNode->setPropertyFieldsDirty(RenderNode::ALPHA);
 }
 
 static void android_view_RenderNode_setHasOverlappingRendering(JNIEnv* env,
         jobject clazz, jlong renderNodePtr, bool hasOverlappingRendering) {
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
     renderNode->mutateStagingProperties().setHasOverlappingRendering(hasOverlappingRendering);
+    renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
 }
 
 static void android_view_RenderNode_setElevation(JNIEnv* env,
         jobject clazz, jlong renderNodePtr, float elevation) {
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
     renderNode->mutateStagingProperties().setElevation(elevation);
+    renderNode->setPropertyFieldsDirty(RenderNode::Z);
 }
 
 static void android_view_RenderNode_setTranslationX(JNIEnv* env,
         jobject clazz, jlong renderNodePtr, float tx) {
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
     renderNode->mutateStagingProperties().setTranslationX(tx);
+    renderNode->setPropertyFieldsDirty(RenderNode::TRANSLATION_X | RenderNode::X);
 }
 
 static void android_view_RenderNode_setTranslationY(JNIEnv* env,
         jobject clazz, jlong renderNodePtr, float ty) {
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
     renderNode->mutateStagingProperties().setTranslationY(ty);
+    renderNode->setPropertyFieldsDirty(RenderNode::TRANSLATION_Y | RenderNode::Y);
 }
 
 static void android_view_RenderNode_setTranslationZ(JNIEnv* env,
         jobject clazz, jlong renderNodePtr, float tz) {
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
     renderNode->mutateStagingProperties().setTranslationZ(tz);
+    renderNode->setPropertyFieldsDirty(RenderNode::TRANSLATION_Z | RenderNode::Z);
 }
 
 static void android_view_RenderNode_setRotation(JNIEnv* env,
         jobject clazz, jlong renderNodePtr, float rotation) {
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
     renderNode->mutateStagingProperties().setRotation(rotation);
+    renderNode->setPropertyFieldsDirty(RenderNode::ROTATION);
 }
 
 static void android_view_RenderNode_setRotationX(JNIEnv* env,
         jobject clazz, jlong renderNodePtr, float rx) {
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
     renderNode->mutateStagingProperties().setRotationX(rx);
+    renderNode->setPropertyFieldsDirty(RenderNode::ROTATION_X);
 }
 
 static void android_view_RenderNode_setRotationY(JNIEnv* env,
         jobject clazz, jlong renderNodePtr, float ry) {
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
     renderNode->mutateStagingProperties().setRotationY(ry);
+    renderNode->setPropertyFieldsDirty(RenderNode::ROTATION_Y);
 }
 
 static void android_view_RenderNode_setScaleX(JNIEnv* env,
         jobject clazz, jlong renderNodePtr, float sx) {
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
     renderNode->mutateStagingProperties().setScaleX(sx);
+    renderNode->setPropertyFieldsDirty(RenderNode::SCALE_X);
 }
 
 static void android_view_RenderNode_setScaleY(JNIEnv* env,
         jobject clazz, jlong renderNodePtr, float sy) {
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
     renderNode->mutateStagingProperties().setScaleY(sy);
+    renderNode->setPropertyFieldsDirty(RenderNode::SCALE_Y);
 }
 
 static void android_view_RenderNode_setPivotX(JNIEnv* env,
         jobject clazz, jlong renderNodePtr, float px) {
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
     renderNode->mutateStagingProperties().setPivotX(px);
+    renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
 }
 
 static void android_view_RenderNode_setPivotY(JNIEnv* env,
         jobject clazz, jlong renderNodePtr, float py) {
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
     renderNode->mutateStagingProperties().setPivotY(py);
+    renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
 }
 
 static void android_view_RenderNode_setCameraDistance(JNIEnv* env,
         jobject clazz, jlong renderNodePtr, float distance) {
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
     renderNode->mutateStagingProperties().setCameraDistance(distance);
+    renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
 }
 
 static void android_view_RenderNode_setLeft(JNIEnv* env,
         jobject clazz, jlong renderNodePtr, int left) {
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
     renderNode->mutateStagingProperties().setLeft(left);
+    renderNode->setPropertyFieldsDirty(RenderNode::X);
 }
 
 static void android_view_RenderNode_setTop(JNIEnv* env,
         jobject clazz, jlong renderNodePtr, int top) {
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
     renderNode->mutateStagingProperties().setTop(top);
+    renderNode->setPropertyFieldsDirty(RenderNode::Y);
 }
 
 static void android_view_RenderNode_setRight(JNIEnv* env,
         jobject clazz, jlong renderNodePtr, int right) {
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
     renderNode->mutateStagingProperties().setRight(right);
+    renderNode->setPropertyFieldsDirty(RenderNode::X);
 }
 
 static void android_view_RenderNode_setBottom(JNIEnv* env,
         jobject clazz, jlong renderNodePtr, int bottom) {
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
     renderNode->mutateStagingProperties().setBottom(bottom);
+    renderNode->setPropertyFieldsDirty(RenderNode::Y);
 }
 
 static void android_view_RenderNode_setLeftTopRightBottom(JNIEnv* env,
@@ -261,18 +290,21 @@
         int right, int bottom) {
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
     renderNode->mutateStagingProperties().setLeftTopRightBottom(left, top, right, bottom);
+    renderNode->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
 }
 
 static void android_view_RenderNode_offsetLeftAndRight(JNIEnv* env,
         jobject clazz, jlong renderNodePtr, float offset) {
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
     renderNode->mutateStagingProperties().offsetLeftRight(offset);
+    renderNode->setPropertyFieldsDirty(RenderNode::X);
 }
 
 static void android_view_RenderNode_offsetTopAndBottom(JNIEnv* env,
         jobject clazz, jlong renderNodePtr, float offset) {
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
     renderNode->mutateStagingProperties().offsetTopBottom(offset);
+    renderNode->setPropertyFieldsDirty(RenderNode::Y);
 }
 
 // ----------------------------------------------------------------------------
diff --git a/core/jni/android_view_RenderNodeAnimator.cpp b/core/jni/android_view_RenderNodeAnimator.cpp
index 5733f60..ea2f96e 100644
--- a/core/jni/android_view_RenderNodeAnimator.cpp
+++ b/core/jni/android_view_RenderNodeAnimator.cpp
@@ -62,7 +62,7 @@
         mWeakThis = NULL;
     }
 
-    virtual void onAnimationFinished(BaseAnimator*) {
+    virtual void onAnimationFinished(BaseRenderNodeAnimator*) {
         JNIEnv* env = getEnv(mJvm);
         env->CallStaticVoidMethod(
                 gRenderNodeAnimatorClassInfo.clazz,
@@ -81,13 +81,6 @@
     return static_cast<RenderPropertyAnimator::RenderProperty>(property);
 }
 
-static inline RenderPropertyAnimator::DeltaValueType toDeltaType(jint deltaType) {
-    LOG_ALWAYS_FATAL_IF(deltaType != RenderPropertyAnimator::DELTA
-            && deltaType != RenderPropertyAnimator::ABSOLUTE,
-            "Invalid delta type %d", deltaType);
-    return static_cast<RenderPropertyAnimator::DeltaValueType>(deltaType);
-}
-
 static inline CanvasPropertyPaintAnimator::PaintField toPaintField(jint field) {
     LOG_ALWAYS_FATAL_IF(field < 0
             || field > CanvasPropertyPaintAnimator::ALPHA,
@@ -96,49 +89,46 @@
 }
 
 static jlong createAnimator(JNIEnv* env, jobject clazz, jobject weakThis,
-        jint propertyRaw, jint deltaTypeRaw, jfloat deltaValue) {
+        jint propertyRaw, jfloat finalValue) {
     RenderPropertyAnimator::RenderProperty property = toRenderProperty(propertyRaw);
-    RenderPropertyAnimator::DeltaValueType deltaType = toDeltaType(deltaTypeRaw);
 
-    BaseAnimator* animator = new RenderPropertyAnimator(property, deltaType, deltaValue);
+    BaseRenderNodeAnimator* animator = new RenderPropertyAnimator(property, finalValue);
     animator->setListener(new AnimationListenerBridge(env, weakThis));
     return reinterpret_cast<jlong>( animator );
 }
 
 static jlong createCanvasPropertyFloatAnimator(JNIEnv* env, jobject clazz,
-        jobject weakThis, jlong canvasPropertyPtr, jint deltaTypeRaw, jfloat deltaValue) {
-    RenderPropertyAnimator::DeltaValueType deltaType = toDeltaType(deltaTypeRaw);
+        jobject weakThis, jlong canvasPropertyPtr, jfloat finalValue) {
     CanvasPropertyPrimitive* canvasProperty = reinterpret_cast<CanvasPropertyPrimitive*>(canvasPropertyPtr);
-    BaseAnimator* animator = new CanvasPropertyPrimitiveAnimator(canvasProperty, deltaType, deltaValue);
+    BaseRenderNodeAnimator* animator = new CanvasPropertyPrimitiveAnimator(canvasProperty, finalValue);
     animator->setListener(new AnimationListenerBridge(env, weakThis));
     return reinterpret_cast<jlong>( animator );
 }
 
 static jlong createCanvasPropertyPaintAnimator(JNIEnv* env, jobject clazz,
         jobject weakThis, jlong canvasPropertyPtr, jint paintFieldRaw,
-        jint deltaTypeRaw, jfloat deltaValue) {
-    RenderPropertyAnimator::DeltaValueType deltaType = toDeltaType(deltaTypeRaw);
+        jfloat finalValue) {
     CanvasPropertyPaint* canvasProperty = reinterpret_cast<CanvasPropertyPaint*>(canvasPropertyPtr);
     CanvasPropertyPaintAnimator::PaintField paintField = toPaintField(paintFieldRaw);
-    BaseAnimator* animator = new CanvasPropertyPaintAnimator(
-            canvasProperty, paintField, deltaType, deltaValue);
+    BaseRenderNodeAnimator* animator = new CanvasPropertyPaintAnimator(
+            canvasProperty, paintField, finalValue);
     animator->setListener(new AnimationListenerBridge(env, weakThis));
     return reinterpret_cast<jlong>( animator );
 }
 
 static void setDuration(JNIEnv* env, jobject clazz, jlong animatorPtr, jint duration) {
     LOG_ALWAYS_FATAL_IF(duration < 0, "Duration cannot be negative");
-    BaseAnimator* animator = reinterpret_cast<BaseAnimator*>(animatorPtr);
+    BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr);
     animator->setDuration(duration);
 }
 
 static jint getDuration(JNIEnv* env, jobject clazz, jlong animatorPtr) {
-    BaseAnimator* animator = reinterpret_cast<BaseAnimator*>(animatorPtr);
+    BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr);
     return static_cast<jint>(animator->duration());
 }
 
 static void setInterpolator(JNIEnv* env, jobject clazz, jlong animatorPtr, jlong interpolatorPtr) {
-    BaseAnimator* animator = reinterpret_cast<BaseAnimator*>(animatorPtr);
+    BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr);
     Interpolator* interpolator = reinterpret_cast<Interpolator*>(interpolatorPtr);
     animator->setInterpolator(interpolator);
 }
@@ -153,9 +143,9 @@
 
 static JNINativeMethod gMethods[] = {
 #ifdef USE_OPENGL_RENDERER
-    { "nCreateAnimator", "(Ljava/lang/ref/WeakReference;IIF)J", (void*) createAnimator },
-    { "nCreateCanvasPropertyFloatAnimator", "(Ljava/lang/ref/WeakReference;JIF)J", (void*) createCanvasPropertyFloatAnimator },
-    { "nCreateCanvasPropertyPaintAnimator", "(Ljava/lang/ref/WeakReference;JIIF)J", (void*) createCanvasPropertyPaintAnimator },
+    { "nCreateAnimator", "(Ljava/lang/ref/WeakReference;IF)J", (void*) createAnimator },
+    { "nCreateCanvasPropertyFloatAnimator", "(Ljava/lang/ref/WeakReference;JF)J", (void*) createCanvasPropertyFloatAnimator },
+    { "nCreateCanvasPropertyPaintAnimator", "(Ljava/lang/ref/WeakReference;JIF)J", (void*) createCanvasPropertyPaintAnimator },
     { "nSetDuration", "(JI)V", (void*) setDuration },
     { "nGetDuration", "(J)I", (void*) getDuration },
     { "nSetInterpolator", "(JJ)V", (void*) setInterpolator },
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index d130a6d..2c10212 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -92,9 +92,9 @@
 
 class OnFinishedEvent {
 public:
-    OnFinishedEvent(BaseAnimator* animator, AnimationListener* listener)
+    OnFinishedEvent(BaseRenderNodeAnimator* animator, AnimationListener* listener)
             : animator(animator), listener(listener) {}
-    sp<BaseAnimator> animator;
+    sp<BaseRenderNodeAnimator> animator;
     sp<AnimationListener> listener;
 };
 
@@ -127,7 +127,7 @@
 
     virtual ~RootRenderNode() {}
 
-    virtual void callOnFinished(BaseAnimator* animator, AnimationListener* listener) {
+    virtual void callOnFinished(BaseRenderNodeAnimator* animator, AnimationListener* listener) {
         OnFinishedEvent event(animator, listener);
         mOnFinishedEvents.push_back(event);
     }
diff --git a/libs/hwui/Animator.cpp b/libs/hwui/Animator.cpp
index a033f86..83eedfb 100644
--- a/libs/hwui/Animator.cpp
+++ b/libs/hwui/Animator.cpp
@@ -27,31 +27,48 @@
 namespace uirenderer {
 
 /************************************************************
- *  Base animator
+ *  BaseRenderNodeAnimator
  ************************************************************/
 
-BaseAnimator::BaseAnimator()
-        : mInterpolator(0)
-        , mPlayState(PENDING)
+BaseRenderNodeAnimator::BaseRenderNodeAnimator(float finalValue)
+        : mFinalValue(finalValue)
+        , mDeltaValue(0)
+        , mFromValue(0)
+        , mInterpolator(0)
+        , mPlayState(NEEDS_START)
         , mStartTime(0)
-        , mDuration(300) {
-
+        , mDuration(300){
 }
 
-BaseAnimator::~BaseAnimator() {
+BaseRenderNodeAnimator::~BaseRenderNodeAnimator() {
     setInterpolator(NULL);
 }
 
-void BaseAnimator::setInterpolator(Interpolator* interpolator) {
+void BaseRenderNodeAnimator::setInterpolator(Interpolator* interpolator) {
     delete mInterpolator;
     mInterpolator = interpolator;
 }
 
-void BaseAnimator::setDuration(nsecs_t duration) {
+void BaseRenderNodeAnimator::setDuration(nsecs_t duration) {
     mDuration = duration;
 }
 
-bool BaseAnimator::animateFrame(TreeInfo& info) {
+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;
+}
+
+void BaseRenderNodeAnimator::setupStartValueIfNecessary(RenderNode* target, TreeInfo& info) {
+    if (mPlayState == NEEDS_START) {
+        setStartValue(getValue(target));
+        mPlayState = PENDING;
+    }
+}
+
+bool BaseRenderNodeAnimator::animate(RenderNode* target, TreeInfo& info) {
     if (mPlayState == PENDING) {
         mPlayState = RUNNING;
         mStartTime = info.frameTimeMs;
@@ -59,7 +76,6 @@
         if (!mInterpolator) {
             setInterpolator(Interpolator::createDefaultInterpolator());
         }
-        onAnimationStarted();
     }
 
     float fraction = 1.0f;
@@ -71,17 +87,16 @@
         }
     }
     fraction = mInterpolator->interpolate(fraction);
-    onAnimationUpdated(fraction);
+    setValue(target, mFromValue + (mDeltaValue * fraction));
 
     if (mPlayState == FINISHED) {
-        onAnimationFinished();
         callOnFinishedListener(info);
         return true;
     }
     return false;
 }
 
-void BaseAnimator::callOnFinishedListener(TreeInfo& info) {
+void BaseRenderNodeAnimator::callOnFinishedListener(TreeInfo& info) {
     if (mListener.get()) {
         if (!info.animationHook) {
             mListener->onAnimationFinished(this);
@@ -92,70 +107,49 @@
 }
 
 /************************************************************
- *  BaseRenderNodeAnimator
- ************************************************************/
-
-BaseRenderNodeAnimator::BaseRenderNodeAnimator(
-                BaseRenderNodeAnimator::DeltaValueType deltaType, float delta)
-        : mTarget(0)
-        , mDeltaValueType(deltaType)
-        , mDeltaValue(delta)
-        , mFromValue(-1) {
-}
-
-bool BaseRenderNodeAnimator::animate(RenderNode* target, TreeInfo& info) {
-    mTarget = target;
-    bool finished = animateFrame(info);
-    mTarget = NULL;
-    return finished;
-}
-
-void BaseRenderNodeAnimator::onAnimationStarted() {
-    mFromValue = getValue();
-
-    if (mDeltaValueType == BaseRenderNodeAnimator::ABSOLUTE) {
-        mDeltaValue = (mDeltaValue - mFromValue);
-        mDeltaValueType = BaseRenderNodeAnimator::DELTA;
-    }
-}
-
-void BaseRenderNodeAnimator::onAnimationUpdated(float fraction) {
-    float value = mFromValue + (mDeltaValue * fraction);
-    setValue(value);
-}
-
-/************************************************************
  *  RenderPropertyAnimator
  ************************************************************/
 
-// Maps RenderProperty enum to accessors
-const RenderPropertyAnimator::PropertyAccessors RenderPropertyAnimator::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 },
+struct RenderPropertyAnimator::PropertyAccessors {
+   RenderNode::DirtyPropertyMask dirtyMask;
+   GetFloatProperty getter;
+   SetFloatProperty setter;
 };
 
-RenderPropertyAnimator::RenderPropertyAnimator(RenderProperty property,
-                DeltaValueType deltaType, float deltaValue)
-        : BaseRenderNodeAnimator(deltaType, deltaValue)
-        , mPropertyAccess(PROPERTY_ACCESSOR_LUT[property]) {
+// Maps RenderProperty enum to accessors
+const RenderPropertyAnimator::PropertyAccessors RenderPropertyAnimator::PROPERTY_ACCESSOR_LUT[] = {
+    {RenderNode::TRANSLATION_X, &RenderProperties::getTranslationX, &RenderProperties::setTranslationX },
+    {RenderNode::TRANSLATION_Y, &RenderProperties::getTranslationY, &RenderProperties::setTranslationY },
+    {RenderNode::TRANSLATION_X, &RenderProperties::getTranslationZ, &RenderProperties::setTranslationZ },
+    {RenderNode::SCALE_X, &RenderProperties::getScaleX, &RenderProperties::setScaleX },
+    {RenderNode::SCALE_Y, &RenderProperties::getScaleY, &RenderProperties::setScaleY },
+    {RenderNode::ROTATION, &RenderProperties::getRotation, &RenderProperties::setRotation },
+    {RenderNode::ROTATION_X, &RenderProperties::getRotationX, &RenderProperties::setRotationX },
+    {RenderNode::ROTATION_Y, &RenderProperties::getRotationY, &RenderProperties::setRotationY },
+    {RenderNode::X, &RenderProperties::getX, &RenderProperties::setX },
+    {RenderNode::Y, &RenderProperties::getY, &RenderProperties::setY },
+    {RenderNode::Z, &RenderProperties::getZ, &RenderProperties::setZ },
+    {RenderNode::ALPHA, &RenderProperties::getAlpha, &RenderProperties::setAlpha },
+};
+
+RenderPropertyAnimator::RenderPropertyAnimator(RenderProperty property, float finalValue)
+        : BaseRenderNodeAnimator(finalValue)
+        , mPropertyAccess(&(PROPERTY_ACCESSOR_LUT[property])) {
 }
 
-float RenderPropertyAnimator::getValue() const {
-    return (target()->animatorProperties().*mPropertyAccess.getter)();
+void RenderPropertyAnimator::onAttached(RenderNode* target) {
+    if (target->isPropertyFieldDirty(mPropertyAccess->dirtyMask)) {
+        setStartValue((target->stagingProperties().*mPropertyAccess->getter)());
+    }
+    (target->mutateStagingProperties().*mPropertyAccess->setter)(finalValue());
 }
 
-void RenderPropertyAnimator::setValue(float value) {
-    (target()->animatorProperties().*mPropertyAccess.setter)(value);
+float RenderPropertyAnimator::getValue(RenderNode* target) const {
+    return (target->properties().*mPropertyAccess->getter)();
+}
+
+void RenderPropertyAnimator::setValue(RenderNode* target, float value) {
+    (target->animatorProperties().*mPropertyAccess->setter)(value);
 }
 
 /************************************************************
@@ -163,16 +157,16 @@
  ************************************************************/
 
 CanvasPropertyPrimitiveAnimator::CanvasPropertyPrimitiveAnimator(
-                CanvasPropertyPrimitive* property, DeltaValueType deltaType, float deltaValue)
-        : BaseRenderNodeAnimator(deltaType, deltaValue)
+                CanvasPropertyPrimitive* property, float finalValue)
+        : BaseRenderNodeAnimator(finalValue)
         , mProperty(property) {
 }
 
-float CanvasPropertyPrimitiveAnimator::getValue() const {
+float CanvasPropertyPrimitiveAnimator::getValue(RenderNode* target) const {
     return mProperty->value;
 }
 
-void CanvasPropertyPrimitiveAnimator::setValue(float value) {
+void CanvasPropertyPrimitiveAnimator::setValue(RenderNode* target, float value) {
     mProperty->value = value;
 }
 
@@ -181,14 +175,13 @@
  ************************************************************/
 
 CanvasPropertyPaintAnimator::CanvasPropertyPaintAnimator(
-                CanvasPropertyPaint* property, PaintField field,
-                DeltaValueType deltaType, float deltaValue)
-        : BaseRenderNodeAnimator(deltaType, deltaValue)
+                CanvasPropertyPaint* property, PaintField field, float finalValue)
+        : BaseRenderNodeAnimator(finalValue)
         , mProperty(property)
         , mField(field) {
 }
 
-float CanvasPropertyPaintAnimator::getValue() const {
+float CanvasPropertyPaintAnimator::getValue(RenderNode* target) const {
     switch (mField) {
     case STROKE_WIDTH:
         return mProperty->value.getStrokeWidth();
@@ -204,7 +197,7 @@
     return static_cast<uint8_t>( c < 0 ? 0 : c > 255 ? 255 : c );
 }
 
-void CanvasPropertyPaintAnimator::setValue(float value) {
+void CanvasPropertyPaintAnimator::setValue(RenderNode* target, float value) {
     switch (mField) {
     case STROKE_WIDTH:
         mProperty->value.setStrokeWidth(value);
diff --git a/libs/hwui/Animator.h b/libs/hwui/Animator.h
index 52a1807..fe88cbf 100644
--- a/libs/hwui/Animator.h
+++ b/libs/hwui/Animator.h
@@ -33,16 +33,14 @@
 
 class AnimationListener : public VirtualLightRefBase {
 public:
-    ANDROID_API virtual void onAnimationFinished(BaseAnimator*) = 0;
+    ANDROID_API virtual void onAnimationFinished(BaseRenderNodeAnimator*) = 0;
 protected:
     ANDROID_API virtual ~AnimationListener() {}
 };
 
-// Helper class to contain generic animator helpers
-class BaseAnimator : public VirtualLightRefBase {
-    PREVENT_COPY_AND_ASSIGN(BaseAnimator);
+class BaseRenderNodeAnimator : public VirtualLightRefBase {
+    PREVENT_COPY_AND_ASSIGN(BaseRenderNodeAnimator);
 public:
-
     ANDROID_API void setInterpolator(Interpolator* interpolator);
     ANDROID_API void setDuration(nsecs_t durationInMs);
     ANDROID_API nsecs_t duration() { return mDuration; }
@@ -50,31 +48,38 @@
         mListener = listener;
     }
 
+    ANDROID_API virtual void onAttached(RenderNode* target) {}
+
+    // Guaranteed to happen before the staging push
+    void setupStartValueIfNecessary(RenderNode* target, TreeInfo& info);
+
+    bool animate(RenderNode* target, TreeInfo& info);
+
     bool isFinished() { return mPlayState == FINISHED; }
+    float finalValue() { return mFinalValue; }
 
 protected:
-    BaseAnimator();
-    virtual ~BaseAnimator();
+    BaseRenderNodeAnimator(float finalValue);
+    virtual ~BaseRenderNodeAnimator();
 
-    // 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(TreeInfo& info);
-
-    // Called when PlayState switches from PENDING to RUNNING
-    virtual void onAnimationStarted() {}
-    virtual void onAnimationUpdated(float fraction) = 0;
-    virtual void onAnimationFinished() {}
+    void setStartValue(float value);
+    virtual float getValue(RenderNode* target) const = 0;
+    virtual void setValue(RenderNode* target, float value) = 0;
 
 private:
     void callOnFinishedListener(TreeInfo& info);
 
     enum PlayState {
+        NEEDS_START,
         PENDING,
         RUNNING,
         FINISHED,
     };
 
+    float mFinalValue;
+    float mDeltaValue;
+    float mFromValue;
+
     Interpolator* mInterpolator;
     PlayState mPlayState;
     long mStartTime;
@@ -83,42 +88,6 @@
    sp<AnimationListener> mListener;
 };
 
-class BaseRenderNodeAnimator : public BaseAnimator {
-public:
-    // Since the UI thread doesn't necessarily know what the current values
-    // actually are and thus can't do the calculations, this is used to inform
-    // the animator how to lazy-resolve the input value
-    enum DeltaValueType {
-        // The delta value represents an absolute value endpoint
-        // mDeltaValue needs to be recalculated to be mDelta = (mDelta - fromValue)
-        // in onAnimationStarted()
-        ABSOLUTE = 0,
-        // The final value represents an offset from the current value
-        // No recalculation is needed
-        DELTA,
-    };
-
-    bool animate(RenderNode* target, TreeInfo& info);
-
-protected:
-    BaseRenderNodeAnimator(DeltaValueType deltaType, float deltaValue);
-
-    RenderNode* target() const { return mTarget; }
-    virtual float getValue() const = 0;
-    virtual void setValue(float value) = 0;
-
-private:
-    virtual void onAnimationStarted();
-    virtual void onAnimationUpdated(float fraction);
-
-    // mTarget is only valid inside animate()
-    RenderNode* mTarget;
-
-    BaseRenderNodeAnimator::DeltaValueType mDeltaValueType;
-    float mDeltaValue;
-    float mFromValue;
-};
-
 class RenderPropertyAnimator : public BaseRenderNodeAnimator {
 public:
     enum RenderProperty {
@@ -136,23 +105,20 @@
         ALPHA,
     };
 
-    ANDROID_API RenderPropertyAnimator(RenderProperty property,
-                DeltaValueType deltaType, float deltaValue);
+    ANDROID_API RenderPropertyAnimator(RenderProperty property, float finalValue);
+
+    ANDROID_API virtual void onAttached(RenderNode* target);
 
 protected:
-    ANDROID_API virtual float getValue() const;
-    ANDROID_API virtual void setValue(float value);
+    virtual float getValue(RenderNode* target) const;
+    virtual void setValue(RenderNode* target, float value);
 
 private:
     typedef void (RenderProperties::*SetFloatProperty)(float value);
     typedef float (RenderProperties::*GetFloatProperty)() const;
 
-    struct PropertyAccessors {
-        GetFloatProperty getter;
-        SetFloatProperty setter;
-    };
-
-    PropertyAccessors mPropertyAccess;
+    struct PropertyAccessors;
+    const PropertyAccessors* mPropertyAccess;
 
     static const PropertyAccessors PROPERTY_ACCESSOR_LUT[];
 };
@@ -160,10 +126,10 @@
 class CanvasPropertyPrimitiveAnimator : public BaseRenderNodeAnimator {
 public:
     ANDROID_API CanvasPropertyPrimitiveAnimator(CanvasPropertyPrimitive* property,
-            DeltaValueType deltaType, float deltaValue);
+            float finalValue);
 protected:
-    ANDROID_API virtual float getValue() const;
-    ANDROID_API virtual void setValue(float value);
+    virtual float getValue(RenderNode* target) const;
+    virtual void setValue(RenderNode* target, float value);
 private:
     sp<CanvasPropertyPrimitive> mProperty;
 };
@@ -176,10 +142,10 @@
     };
 
     ANDROID_API CanvasPropertyPaintAnimator(CanvasPropertyPaint* property,
-            PaintField field, DeltaValueType deltaType, float deltaValue);
+            PaintField field, float finalValue);
 protected:
-    ANDROID_API virtual float getValue() const;
-    ANDROID_API virtual void setValue(float value);
+    virtual float getValue(RenderNode* target) const;
+    virtual void setValue(RenderNode* target, float value);
 private:
     sp<CanvasPropertyPaint> mProperty;
     PaintField mField;
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index fba482d..d4ff4a3 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -53,7 +53,7 @@
 }
 
 RenderNode::RenderNode()
-        : mNeedsPropertiesSync(false)
+        : mDirtyPropertyFields(0)
         , mNeedsDisplayListDataSync(false)
         , mDisplayListData(0)
         , mStagingDisplayListData(0)
@@ -109,23 +109,37 @@
     prepareSubTree(info, mDisplayListData);
 }
 
-static bool is_finished(const sp<BaseRenderNodeAnimator>& animator) {
-    return animator->isFinished();
-}
+class PushAnimatorsFunctor {
+public:
+    PushAnimatorsFunctor(RenderNode* target, TreeInfo& info)
+            : mTarget(target), mInfo(info) {}
+
+    bool operator() (const sp<BaseRenderNodeAnimator>& animator) {
+        animator->setupStartValueIfNecessary(mTarget, mInfo);
+        return animator->isFinished();
+    }
+private:
+    RenderNode* mTarget;
+    TreeInfo& mInfo;
+};
 
 void RenderNode::pushStagingChanges(TreeInfo& info) {
-    if (mNeedsPropertiesSync) {
-        mNeedsPropertiesSync = false;
-        mProperties = mStagingProperties;
-    }
+    // Push the animators first so that setupStartValueIfNecessary() is called
+    // before properties() is trampled by stagingProperties(), as they are
+    // required by some animators.
     if (mNeedsAnimatorsSync) {
         mAnimators.resize(mStagingAnimators.size());
         std::vector< sp<BaseRenderNodeAnimator> >::iterator it;
+        PushAnimatorsFunctor functor(this, info);
         // hint: this means copy_if_not()
         it = std::remove_copy_if(mStagingAnimators.begin(), mStagingAnimators.end(),
-                mAnimators.begin(), is_finished);
+                mAnimators.begin(), functor);
         mAnimators.resize(std::distance(mAnimators.begin(), it));
     }
+    if (mDirtyPropertyFields) {
+        mDirtyPropertyFields = 0;
+        mProperties = mStagingProperties;
+    }
     if (mNeedsDisplayListDataSync) {
         mNeedsDisplayListDataSync = false;
         // Do a push pass on the old tree to handle freeing DisplayListData
@@ -144,7 +158,7 @@
     AnimateFunctor(RenderNode* target, TreeInfo& info)
             : mTarget(target), mInfo(info) {}
 
-    bool operator() (sp<BaseRenderNodeAnimator>& animator) {
+    bool operator() (const sp<BaseRenderNodeAnimator>& animator) {
         return animator->animate(mTarget, mInfo);
     }
 private:
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index bc62ee1..1811a7b 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -82,6 +82,22 @@
  */
 class RenderNode : public VirtualLightRefBase {
 public:
+    enum DirtyPropertyMask {
+        GENERIC         = 1 << 1,
+        TRANSLATION_X   = 1 << 2,
+        TRANSLATION_Y   = 1 << 3,
+        TRANSLATION_Z   = 1 << 4,
+        SCALE_X         = 1 << 5,
+        SCALE_Y         = 1 << 6,
+        ROTATION        = 1 << 7,
+        ROTATION_X      = 1 << 8,
+        ROTATION_Y      = 1 << 9,
+        X               = 1 << 10,
+        Y               = 1 << 11,
+        Z               = 1 << 12,
+        ALPHA           = 1 << 13,
+    };
+
     ANDROID_API RenderNode();
     ANDROID_API virtual ~RenderNode();
 
@@ -123,6 +139,14 @@
         }
     }
 
+    bool isPropertyFieldDirty(DirtyPropertyMask field) const {
+        return mDirtyPropertyFields & field;
+    }
+
+    void setPropertyFieldsDirty(uint32_t fields) {
+        mDirtyPropertyFields |= fields;
+    }
+
     const RenderProperties& properties() {
         return mProperties;
     }
@@ -136,7 +160,6 @@
     }
 
     RenderProperties& mutateStagingProperties() {
-        mNeedsPropertiesSync = true;
         return mStagingProperties;
     }
 
@@ -152,6 +175,7 @@
 
     // UI thread only!
     ANDROID_API void addAnimator(const sp<BaseRenderNodeAnimator>& animator) {
+        animator->onAttached(this);
         mStagingAnimators.insert(animator);
         mNeedsAnimatorsSync = true;
     }
@@ -227,7 +251,7 @@
 
     String8 mName;
 
-    bool mNeedsPropertiesSync;
+    uint32_t mDirtyPropertyFields;
     RenderProperties mProperties;
     RenderProperties mStagingProperties;
 
diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h
index fc5994c..d4a23b8 100644
--- a/libs/hwui/TreeInfo.h
+++ b/libs/hwui/TreeInfo.h
@@ -21,12 +21,12 @@
 namespace android {
 namespace uirenderer {
 
-class BaseAnimator;
+class BaseRenderNodeAnimator;
 class AnimationListener;
 
 class AnimationHook {
 public:
-    virtual void callOnFinished(BaseAnimator* animator, AnimationListener* listener) = 0;
+    virtual void callOnFinished(BaseRenderNodeAnimator* animator, AnimationListener* listener) = 0;
 protected:
     ~AnimationHook() {}
 };
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java
index 1d0a806..e4ea9367 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java
@@ -109,26 +109,27 @@
             mToggle = !mToggle;
 
             mRunningAnimations.add(new RenderNodeAnimator(
-                    mX, RenderNodeAnimator.DELTA_TYPE_ABSOLUTE, mToggle ? 400.0f : 200.0f));
+                    mX, mToggle ? 400.0f : 200.0f));
 
             mRunningAnimations.add(new RenderNodeAnimator(
-                    mY, RenderNodeAnimator.DELTA_TYPE_ABSOLUTE, mToggle ? 600.0f : 200.0f));
+                    mY, mToggle ? 600.0f : 200.0f));
 
             mRunningAnimations.add(new RenderNodeAnimator(
-                    mRadius, RenderNodeAnimator.DELTA_TYPE_ABSOLUTE, mToggle ? 250.0f : 150.0f));
+                    mRadius, mToggle ? 250.0f : 150.0f));
 
             mRunningAnimations.add(new RenderNodeAnimator(
                     mPaint, RenderNodeAnimator.PAINT_ALPHA,
-                    RenderNodeAnimator.DELTA_TYPE_ABSOLUTE, mToggle ? 64.0f : 255.0f));
+                    mToggle ? 64.0f : 255.0f));
 
             mRunningAnimations.add(new RenderNodeAnimator(
                     mPaint, RenderNodeAnimator.PAINT_STROKE_WIDTH,
-                    RenderNodeAnimator.DELTA_TYPE_ABSOLUTE, mToggle ? 5.0f : 60.0f));
+                    mToggle ? 5.0f : 60.0f));
 
             TimeInterpolator interp = new OvershootInterpolator(3.0f);
             for (int i = 0; i < mRunningAnimations.size(); i++) {
                 RenderNodeAnimator anim = mRunningAnimations.get(i);
                 anim.setInterpolator(interp);
+                anim.setDuration(1000);
                 anim.start(this);
             }
 
diff --git a/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java b/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java
index 8f9cf58..b5b12d8 100644
--- a/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java
+++ b/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java
@@ -5,6 +5,7 @@
 import android.content.Intent;
 import android.os.Bundle;
 import android.os.Handler;
+import android.util.Log;
 import android.view.HardwareRenderer;
 import android.view.RenderNodeAnimator;
 import android.view.View;
@@ -73,14 +74,20 @@
             float delta = (pos - clickedPosition) * 1.1f;
             if (delta == 0) delta = -1;
             RenderNodeAnimator animator = new RenderNodeAnimator(
-                    RenderNodeAnimator.TRANSLATION_Y, RenderNodeAnimator.DELTA_TYPE_DELTA, dy * delta);
+                    RenderNodeAnimator.TRANSLATION_Y, dy * delta);
             animator.setDuration(DURATION);
+            if (child == clickedView) logTranslationY(clickedView);
             animator.start(child);
+            if (child == clickedView) logTranslationY(clickedView);
         }
         //mHandler.postDelayed(mLaunchActivity, (long) (DURATION * .4));
         mLaunchActivity.run();
     }
 
+    private void logTranslationY(View v) {
+        Log.d("RTTest", "View has translationY: " + v.getTranslationY());
+    }
+
     private Runnable mLaunchActivity = new Runnable() {
 
         @Override