diff --git a/core/java/android/view/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java index b95f9a4cab526..7feca3076a766 100644 --- a/core/java/android/view/RenderNodeAnimator.java +++ b/core/java/android/view/RenderNodeAnimator.java @@ -189,9 +189,6 @@ public class RenderNodeAnimator extends Animator { } private void doStart() { - mState = STATE_RUNNING; - nStart(mNativePtr.get(), this); - // Alpha is a special snowflake that has the canonical value stored // in mTransformationInfo instead of in RenderNode, so we need to update // it with the final value here. @@ -201,7 +198,7 @@ public class RenderNodeAnimator extends Animator { mViewTarget.mTransformationInfo.mAlpha = mFinalValue; } - notifyStartListeners(); + moveToRunningState(); if (mViewTarget != null) { // Kick off a frame to start the process @@ -209,6 +206,12 @@ public class RenderNodeAnimator extends Animator { } } + private void moveToRunningState() { + mState = STATE_RUNNING; + nStart(mNativePtr.get(), this); + notifyStartListeners(); + } + private void notifyStartListeners() { final ArrayList listeners = cloneListeners(); final int numListeners = listeners == null ? 0 : listeners.size(); @@ -222,7 +225,7 @@ public class RenderNodeAnimator extends Animator { if (mState != STATE_PREPARE && mState != STATE_FINISHED) { if (mState == STATE_DELAYED) { getHelper().removeDelayedAnimation(this); - notifyStartListeners(); + moveToRunningState(); } nEnd(mNativePtr.get()); @@ -242,7 +245,15 @@ public class RenderNodeAnimator extends Animator { @Override public void end() { if (mState != STATE_FINISHED) { + if (mState < STATE_RUNNING) { + getHelper().removeDelayedAnimation(this); + doStart(); + } nEnd(mNativePtr.get()); + if (mViewTarget != null) { + // Kick off a frame to flush the state change + mViewTarget.invalidateViewProperty(true, false); + } } } diff --git a/core/jni/android_view_RenderNodeAnimator.cpp b/core/jni/android_view_RenderNodeAnimator.cpp index 90b311a96e353..b6f19c430f919 100644 --- a/core/jni/android_view_RenderNodeAnimator.cpp +++ b/core/jni/android_view_RenderNodeAnimator.cpp @@ -47,6 +47,15 @@ static JNIEnv* getEnv(JavaVM* vm) { return env; } +class AnimationListenerLifecycleChecker : public AnimationListener { +public: + virtual void onAnimationFinished(BaseRenderNodeAnimator* animator) { + LOG_ALWAYS_FATAL("Lifecycle failure, nStart(%p) wasn't called", animator); + } +}; + +static AnimationListenerLifecycleChecker sLifecycleChecker; + class AnimationListenerBridge : public AnimationListener { public: // This holds a strong reference to a Java WeakReference object. This avoids @@ -102,6 +111,7 @@ static jlong createAnimator(JNIEnv* env, jobject clazz, jint propertyRaw, jfloat finalValue) { RenderPropertyAnimator::RenderProperty property = toRenderProperty(propertyRaw); BaseRenderNodeAnimator* animator = new RenderPropertyAnimator(property, finalValue); + animator->setListener(&sLifecycleChecker); return reinterpret_cast( animator ); } @@ -109,6 +119,7 @@ static jlong createCanvasPropertyFloatAnimator(JNIEnv* env, jobject clazz, jlong canvasPropertyPtr, jfloat finalValue) { CanvasPropertyPrimitive* canvasProperty = reinterpret_cast(canvasPropertyPtr); BaseRenderNodeAnimator* animator = new CanvasPropertyPrimitiveAnimator(canvasProperty, finalValue); + animator->setListener(&sLifecycleChecker); return reinterpret_cast( animator ); } @@ -119,12 +130,14 @@ static jlong createCanvasPropertyPaintAnimator(JNIEnv* env, jobject clazz, CanvasPropertyPaintAnimator::PaintField paintField = toPaintField(paintFieldRaw); BaseRenderNodeAnimator* animator = new CanvasPropertyPaintAnimator( canvasProperty, paintField, finalValue); + animator->setListener(&sLifecycleChecker); return reinterpret_cast( animator ); } static jlong createRevealAnimator(JNIEnv* env, jobject clazz, jint centerX, jint centerY, jfloat startRadius, jfloat endRadius) { BaseRenderNodeAnimator* animator = new RevealAnimator(centerX, centerY, startRadius, endRadius); + animator->setListener(&sLifecycleChecker); return reinterpret_cast( animator ); } @@ -163,9 +176,7 @@ static void setAllowRunningAsync(JNIEnv* env, jobject clazz, jlong animatorPtr, static void start(JNIEnv* env, jobject clazz, jlong animatorPtr, jobject finishListener) { BaseRenderNodeAnimator* animator = reinterpret_cast(animatorPtr); - if (finishListener) { - animator->setListener(new AnimationListenerBridge(env, finishListener)); - } + animator->setListener(new AnimationListenerBridge(env, finishListener)); animator->start(); } @@ -200,6 +211,9 @@ static JNINativeMethod gMethods[] = { }; int register_android_view_RenderNodeAnimator(JNIEnv* env) { +#ifdef USE_OPENGL_RENDERER + sLifecycleChecker.incStrong(0); +#endif gRenderNodeAnimatorClassInfo.clazz = FindClassOrDie(env, kClassPathName); gRenderNodeAnimatorClassInfo.clazz = MakeGlobalRefOrDie(env, gRenderNodeAnimatorClassInfo.clazz);