am 14c43689: Merge "Fix issue with RNA destruction mid-animation" into lmp-mr1-dev

* commit '14c436897ca56800a3758008f0631c559a898967':
  Fix issue with RNA destruction mid-animation
This commit is contained in:
John Reck
2014-12-09 22:08:42 +00:00
committed by Android Git Automerger
3 changed files with 74 additions and 16 deletions

View File

@@ -148,6 +148,10 @@ public class RenderNodeAnimator extends Animator {
if (mState != STATE_PREPARE) { if (mState != STATE_PREPARE) {
throw new IllegalStateException("Animator has already started, cannot change it now!"); throw new IllegalStateException("Animator has already started, cannot change it now!");
} }
if (mNativePtr == null) {
throw new IllegalStateException("Animator's target has been destroyed "
+ "(trying to modify an animation after activity destroy?)");
}
} }
static boolean isNativeInterpolator(TimeInterpolator interpolator) { static boolean isNativeInterpolator(TimeInterpolator interpolator) {
@@ -180,7 +184,10 @@ public class RenderNodeAnimator extends Animator {
mState = STATE_DELAYED; mState = STATE_DELAYED;
applyInterpolator(); applyInterpolator();
if (mStartDelay <= 0 || !mUiThreadHandlesDelay) { if (mNativePtr == null) {
// It's dead, immediately cancel
cancel();
} else if (mStartDelay <= 0 || !mUiThreadHandlesDelay) {
nSetStartDelay(mNativePtr.get(), mStartDelay); nSetStartDelay(mNativePtr.get(), mStartDelay);
doStart(); doStart();
} else { } else {
@@ -208,7 +215,9 @@ public class RenderNodeAnimator extends Animator {
private void moveToRunningState() { private void moveToRunningState() {
mState = STATE_RUNNING; mState = STATE_RUNNING;
nStart(mNativePtr.get(), this); if (mNativePtr != null) {
nStart(mNativePtr.get());
}
notifyStartListeners(); notifyStartListeners();
} }
@@ -227,7 +236,6 @@ public class RenderNodeAnimator extends Animator {
getHelper().removeDelayedAnimation(this); getHelper().removeDelayedAnimation(this);
moveToRunningState(); moveToRunningState();
} }
nEnd(mNativePtr.get());
final ArrayList<AnimatorListener> listeners = cloneListeners(); final ArrayList<AnimatorListener> listeners = cloneListeners();
final int numListeners = listeners == null ? 0 : listeners.size(); final int numListeners = listeners == null ? 0 : listeners.size();
@@ -235,10 +243,7 @@ public class RenderNodeAnimator extends Animator {
listeners.get(i).onAnimationCancel(this); listeners.get(i).onAnimationCancel(this);
} }
if (mViewTarget != null) { end();
// Kick off a frame to flush the state change
mViewTarget.invalidateViewProperty(true, false);
}
} }
} }
@@ -249,10 +254,15 @@ public class RenderNodeAnimator extends Animator {
getHelper().removeDelayedAnimation(this); getHelper().removeDelayedAnimation(this);
doStart(); doStart();
} }
nEnd(mNativePtr.get()); if (mNativePtr != null) {
if (mViewTarget != null) { nEnd(mNativePtr.get());
// Kick off a frame to flush the state change if (mViewTarget != null) {
mViewTarget.invalidateViewProperty(true, false); // Kick off a frame to flush the state change
mViewTarget.invalidateViewProperty(true, false);
}
} else {
// It's already dead, jump to onFinish
onFinished();
} }
} }
} }
@@ -281,9 +291,11 @@ public class RenderNodeAnimator extends Animator {
} }
private void setTarget(RenderNode node) { private void setTarget(RenderNode node) {
checkMutable();
if (mTarget != null) { if (mTarget != null) {
throw new IllegalStateException("Target already set!"); throw new IllegalStateException("Target already set!");
} }
nSetListener(mNativePtr.get(), this);
mTarget = node; mTarget = node;
mTarget.addAnimator(this); mTarget.addAnimator(this);
} }
@@ -346,6 +358,12 @@ public class RenderNodeAnimator extends Animator {
} }
protected void onFinished() { protected void onFinished() {
if (mState == STATE_PREPARE) {
// Unlikely but possible, the native side has been destroyed
// before we have started.
releaseNativePtr();
return;
}
if (mState == STATE_DELAYED) { if (mState == STATE_DELAYED) {
getHelper().removeDelayedAnimation(this); getHelper().removeDelayedAnimation(this);
notifyStartListeners(); notifyStartListeners();
@@ -361,8 +379,14 @@ public class RenderNodeAnimator extends Animator {
// Release the native object, as it has a global reference to us. This // Release the native object, as it has a global reference to us. This
// breaks the cyclic reference chain, and allows this object to be // breaks the cyclic reference chain, and allows this object to be
// GC'd // GC'd
mNativePtr.release(); releaseNativePtr();
mNativePtr = null; }
private void releaseNativePtr() {
if (mNativePtr != null) {
mNativePtr.release();
mNativePtr = null;
}
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@@ -484,7 +508,8 @@ public class RenderNodeAnimator extends Animator {
private static native void nSetStartDelay(long nativePtr, long startDelay); private static native void nSetStartDelay(long nativePtr, long startDelay);
private static native void nSetInterpolator(long animPtr, long interpolatorPtr); private static native void nSetInterpolator(long animPtr, long interpolatorPtr);
private static native void nSetAllowRunningAsync(long animPtr, boolean mayRunAsync); private static native void nSetAllowRunningAsync(long animPtr, boolean mayRunAsync);
private static native void nSetListener(long animPtr, RenderNodeAnimator listener);
private static native void nStart(long animPtr, RenderNodeAnimator finishListener); private static native void nStart(long animPtr);
private static native void nEnd(long animPtr); private static native void nEnd(long animPtr);
} }

View File

@@ -177,9 +177,13 @@ static void setAllowRunningAsync(JNIEnv* env, jobject clazz, jlong animatorPtr,
animator->setAllowRunningAsync(mayRunAsync); animator->setAllowRunningAsync(mayRunAsync);
} }
static void start(JNIEnv* env, jobject clazz, jlong animatorPtr, jobject finishListener) { static void setListener(JNIEnv* env, jobject clazz, jlong animatorPtr, jobject finishListener) {
BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr); BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr);
animator->setListener(new AnimationListenerBridge(env, finishListener)); animator->setListener(new AnimationListenerBridge(env, finishListener));
}
static void start(JNIEnv* env, jobject clazz, jlong animatorPtr) {
BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr);
animator->start(); animator->start();
} }
@@ -208,7 +212,8 @@ static JNINativeMethod gMethods[] = {
{ "nSetStartDelay", "(JJ)V", (void*) setStartDelay }, { "nSetStartDelay", "(JJ)V", (void*) setStartDelay },
{ "nSetInterpolator", "(JJ)V", (void*) setInterpolator }, { "nSetInterpolator", "(JJ)V", (void*) setInterpolator },
{ "nSetAllowRunningAsync", "(JZ)V", (void*) setAllowRunningAsync }, { "nSetAllowRunningAsync", "(JZ)V", (void*) setAllowRunningAsync },
{ "nStart", "(JLandroid/view/RenderNodeAnimator;)V", (void*) start }, { "nSetListener", "(JLandroid/view/RenderNodeAnimator;)V", (void*) setListener},
{ "nStart", "(J)V", (void*) start},
{ "nEnd", "(J)V", (void*) end }, { "nEnd", "(J)V", (void*) end },
#endif #endif
}; };

View File

@@ -17,12 +17,14 @@
package com.android.test.hwui; package com.android.test.hwui;
import android.animation.Animator; import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.AnimatorSet; import android.animation.AnimatorSet;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Color; import android.graphics.Color;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
import android.view.ViewAnimationUtils; import android.view.ViewAnimationUtils;
@@ -37,6 +39,29 @@ public class RevealActivity extends Activity implements OnClickListener {
private boolean mShouldBlock; private boolean mShouldBlock;
private int mIteration = 0; private int mIteration = 0;
private AnimatorListener mListener = new AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
Log.d("Reveal", "onAnimatorStart " + animation);
}
@Override
public void onAnimationRepeat(Animator animation) {
Log.d("Reveal", "onAnimationRepeat " + animation);
}
@Override
public void onAnimationEnd(Animator animation) {
Log.d("Reveal", "onAnimationEnd " + animation);
}
@Override
public void onAnimationCancel(Animator animation) {
Log.d("Reveal", "onAnimationCancel " + animation);
}
};
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@@ -59,6 +84,8 @@ public class RevealActivity extends Activity implements OnClickListener {
Animator animator = ViewAnimationUtils.createCircularReveal(view, Animator animator = ViewAnimationUtils.createCircularReveal(view,
view.getWidth() / 2, view.getHeight() / 2, view.getWidth() / 2, view.getHeight() / 2,
0, Math.max(view.getWidth(), view.getHeight())); 0, Math.max(view.getWidth(), view.getHeight()));
Log.d("Reveal", "Calling start...");
animator.addListener(mListener);
if (mIteration < 2) { if (mIteration < 2) {
animator.setDuration(DURATION); animator.setDuration(DURATION);
animator.start(); animator.start();
@@ -66,6 +93,7 @@ public class RevealActivity extends Activity implements OnClickListener {
AnimatorSet set = new AnimatorSet(); AnimatorSet set = new AnimatorSet();
set.playTogether(animator); set.playTogether(animator);
set.setDuration(DURATION); set.setDuration(DURATION);
set.addListener(mListener);
set.start(); set.start();
} }