diff options
author | Derek Sollenberger <djsollen@google.com> | 2020-02-14 16:32:50 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2020-02-14 16:32:50 +0000 |
commit | db8164c0ac68ffa4f2c7c2d97f68b21f3eaa68b5 (patch) | |
tree | 845085e575a559f05794b0e21eb0a1c57be8dd56 /graphics | |
parent | 47f42fedeed263116b885e13c1658ee7407d362b (diff) | |
parent | 8c2f6b6e159512d2438a0b9504a7656157fab4c5 (diff) |
Merge "Move RenderNodeAnimator to android.graphics.animation package"
Diffstat (limited to 'graphics')
8 files changed, 731 insertions, 5 deletions
diff --git a/graphics/java/android/graphics/RenderNode.java b/graphics/java/android/graphics/RenderNode.java index 3835b2d493c5..752695fd8e52 100644 --- a/graphics/java/android/graphics/RenderNode.java +++ b/graphics/java/android/graphics/RenderNode.java @@ -22,8 +22,8 @@ import android.annotation.FloatRange; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.graphics.animation.RenderNodeAnimator; import android.view.NativeVectorDrawableAnimator; -import android.view.RenderNodeAnimator; import android.view.Surface; import android.view.View; diff --git a/graphics/java/android/graphics/animation/FallbackLUTInterpolator.java b/graphics/java/android/graphics/animation/FallbackLUTInterpolator.java new file mode 100644 index 000000000000..36062c141ed2 --- /dev/null +++ b/graphics/java/android/graphics/animation/FallbackLUTInterpolator.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.graphics.animation; + +import android.animation.TimeInterpolator; +import android.util.TimeUtils; +import android.view.Choreographer; + +/** + * Interpolator that builds a lookup table to use. This is a fallback for + * building a native interpolator from a TimeInterpolator that is not marked + * with {@link HasNativeInterpolator} + * + * This implements TimeInterpolator to allow for easier interop with Animators + * @hide + */ +@HasNativeInterpolator +public class FallbackLUTInterpolator implements NativeInterpolator, TimeInterpolator { + + // If the duration of an animation is more than 300 frames, we cap the sample size to 300. + private static final int MAX_SAMPLE_POINTS = 300; + private TimeInterpolator mSourceInterpolator; + private final float[] mLut; + + /** + * Used to cache the float[] LUT for use across multiple native + * interpolator creation + */ + public FallbackLUTInterpolator(TimeInterpolator interpolator, long duration) { + mSourceInterpolator = interpolator; + mLut = createLUT(interpolator, duration); + } + + private static float[] createLUT(TimeInterpolator interpolator, long duration) { + long frameIntervalNanos = Choreographer.getInstance().getFrameIntervalNanos(); + int animIntervalMs = (int) (frameIntervalNanos / TimeUtils.NANOS_PER_MS); + // We need 2 frame values as the minimal. + int numAnimFrames = Math.max(2, (int) Math.ceil(((double) duration) / animIntervalMs)); + numAnimFrames = Math.min(numAnimFrames, MAX_SAMPLE_POINTS); + float[] values = new float[numAnimFrames]; + float lastFrame = numAnimFrames - 1; + for (int i = 0; i < numAnimFrames; i++) { + float inValue = i / lastFrame; + values[i] = interpolator.getInterpolation(inValue); + } + return values; + } + + @Override + public long createNativeInterpolator() { + return NativeInterpolatorFactory.createLutInterpolator(mLut); + } + + /** + * Used to create a one-shot float[] LUT & native interpolator + */ + public static long createNativeInterpolator(TimeInterpolator interpolator, long duration) { + float[] lut = createLUT(interpolator, duration); + return NativeInterpolatorFactory.createLutInterpolator(lut); + } + + @Override + public float getInterpolation(float input) { + return mSourceInterpolator.getInterpolation(input); + } +} diff --git a/graphics/java/android/graphics/animation/HasNativeInterpolator.java b/graphics/java/android/graphics/animation/HasNativeInterpolator.java new file mode 100644 index 000000000000..c53d5a42524d --- /dev/null +++ b/graphics/java/android/graphics/animation/HasNativeInterpolator.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.graphics.animation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * This is a class annotation that signals that it is safe to create + * a native interpolator counterpart via {@link NativeInterpolator} + * + * The idea here is to prevent subclasses of interpolators from being treated as a + * NativeInterpolator, and instead have them fall back to the LUT & LERP + * method like a custom interpolator. + * + * @hide + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE}) +public @interface HasNativeInterpolator { +} diff --git a/graphics/java/android/graphics/animation/NativeInterpolator.java b/graphics/java/android/graphics/animation/NativeInterpolator.java new file mode 100644 index 000000000000..1e6fea8da466 --- /dev/null +++ b/graphics/java/android/graphics/animation/NativeInterpolator.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.graphics.animation; + +/** + * @hide + */ +public interface NativeInterpolator { + /** + * Generates a native interpolator object that can be used by HardwareRenderer to draw + * RenderNodes. + * @return ptr to native object + */ + long createNativeInterpolator(); +} diff --git a/graphics/java/android/graphics/animation/NativeInterpolatorFactory.java b/graphics/java/android/graphics/animation/NativeInterpolatorFactory.java new file mode 100644 index 000000000000..38866145ee50 --- /dev/null +++ b/graphics/java/android/graphics/animation/NativeInterpolatorFactory.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.graphics.animation; + +import android.animation.TimeInterpolator; + +/** + * Static utility class for constructing native interpolators to keep the + * JNI simpler + * + * @hide + */ +public final class NativeInterpolatorFactory { + private NativeInterpolatorFactory() {} + + /** + * Create a native interpolator from the provided param generating a LUT variant if a native + * implementation does not exist. + */ + public static long createNativeInterpolator(TimeInterpolator interpolator, long + duration) { + if (interpolator == null) { + return createLinearInterpolator(); + } else if (RenderNodeAnimator.isNativeInterpolator(interpolator)) { + return ((NativeInterpolator) interpolator).createNativeInterpolator(); + } else { + return FallbackLUTInterpolator.createNativeInterpolator(interpolator, duration); + } + } + + /** Creates a specialized native interpolator for Accelerate/Decelerate */ + public static native long createAccelerateDecelerateInterpolator(); + /** Creates a specialized native interpolator for Accelerate */ + public static native long createAccelerateInterpolator(float factor); + /** Creates a specialized native interpolator for Anticipate */ + public static native long createAnticipateInterpolator(float tension); + /** Creates a specialized native interpolator for Anticipate with Overshoot */ + public static native long createAnticipateOvershootInterpolator(float tension); + /** Creates a specialized native interpolator for Bounce */ + public static native long createBounceInterpolator(); + /** Creates a specialized native interpolator for Cycle */ + public static native long createCycleInterpolator(float cycles); + /** Creates a specialized native interpolator for Decelerate */ + public static native long createDecelerateInterpolator(float factor); + /** Creates a specialized native interpolator for Linear interpolation */ + public static native long createLinearInterpolator(); + /** Creates a specialized native interpolator for Overshoot */ + public static native long createOvershootInterpolator(float tension); + /** Creates a specialized native interpolator for along traveling along a Path */ + public static native long createPathInterpolator(float[] x, float[] y); + /** Creates a specialized native interpolator for LUT */ + public static native long createLutInterpolator(float[] values); +} diff --git a/graphics/java/android/graphics/animation/RenderNodeAnimator.java b/graphics/java/android/graphics/animation/RenderNodeAnimator.java new file mode 100644 index 000000000000..282b2f959fc4 --- /dev/null +++ b/graphics/java/android/graphics/animation/RenderNodeAnimator.java @@ -0,0 +1,513 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.graphics.animation; + +import android.animation.Animator; +import android.animation.TimeInterpolator; +import android.animation.ValueAnimator; +import android.graphics.CanvasProperty; +import android.graphics.Paint; +import android.graphics.RecordingCanvas; +import android.graphics.RenderNode; +import android.os.Handler; +import android.os.Looper; +import android.view.Choreographer; + +import com.android.internal.util.VirtualRefBasePtr; + +import java.util.ArrayList; + +/** + * @hide + */ +public class RenderNodeAnimator extends Animator { + // Keep in sync with enum RenderProperty in Animator.h + public static final int TRANSLATION_X = 0; + public static final int TRANSLATION_Y = 1; + public static final int TRANSLATION_Z = 2; + public static final int SCALE_X = 3; + public static final int SCALE_Y = 4; + public static final int ROTATION = 5; + public static final int ROTATION_X = 6; + public static final int ROTATION_Y = 7; + public static final int X = 8; + public static final int Y = 9; + public static final int Z = 10; + public static final int ALPHA = 11; + // The last value in the enum, used for array size initialization + public static final int LAST_VALUE = ALPHA; + + // Keep in sync with enum PaintFields in Animator.h + public static final int PAINT_STROKE_WIDTH = 0; + + /** + * Field for the Paint alpha channel, which should be specified as a value + * between 0 and 255. + */ + public static final int PAINT_ALPHA = 1; + + private VirtualRefBasePtr mNativePtr; + + private Handler mHandler; + private RenderNode mTarget; + private ViewListener mViewListener; + private int mRenderProperty = -1; + private float mFinalValue; + private TimeInterpolator mInterpolator; + + private static final int STATE_PREPARE = 0; + private static final int STATE_DELAYED = 1; + private static final int STATE_RUNNING = 2; + private static final int STATE_FINISHED = 3; + private int mState = STATE_PREPARE; + + private long mUnscaledDuration = 300; + private long mUnscaledStartDelay = 0; + // If this is true, we will run any start delays on the UI thread. This is + // the safe default, and is necessary to ensure start listeners fire at + // the correct time. Animators created by RippleDrawable (the + // CanvasProperty<> ones) do not have this expectation, and as such will + // set this to false so that the renderthread handles the startdelay instead + private final boolean mUiThreadHandlesDelay; + private long mStartDelay = 0; + private long mStartTime; + + /** + * Interface used by the view system to update the view hierarchy in conjunction + * with this animator. + */ + public interface ViewListener { + /** notify the listener that an alpha animation has begun. */ + void onAlphaAnimationStart(float finalAlpha); + /** notify the listener that the animator has mutated a value that requires invalidation */ + void invalidateParent(boolean forceRedraw); + } + + public RenderNodeAnimator(int property, float finalValue) { + mRenderProperty = property; + mFinalValue = finalValue; + mUiThreadHandlesDelay = true; + init(nCreateAnimator(property, finalValue)); + } + + public RenderNodeAnimator(CanvasProperty<Float> property, float finalValue) { + init(nCreateCanvasPropertyFloatAnimator( + property.getNativeContainer(), finalValue)); + mUiThreadHandlesDelay = false; + } + + /** + * Creates a new render node animator for a field on a Paint property. + * + * @param property The paint property to target + * @param paintField Paint field to animate, one of {@link #PAINT_ALPHA} or + * {@link #PAINT_STROKE_WIDTH} + * @param finalValue The target value for the property + */ + public RenderNodeAnimator(CanvasProperty<Paint> property, int paintField, float finalValue) { + init(nCreateCanvasPropertyPaintAnimator( + property.getNativeContainer(), paintField, finalValue)); + mUiThreadHandlesDelay = false; + } + + public RenderNodeAnimator(int x, int y, float startRadius, float endRadius) { + init(nCreateRevealAnimator(x, y, startRadius, endRadius)); + mUiThreadHandlesDelay = true; + } + + private void init(long ptr) { + mNativePtr = new VirtualRefBasePtr(ptr); + } + + private void checkMutable() { + if (mState != STATE_PREPARE) { + 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) { + return interpolator.getClass().isAnnotationPresent(HasNativeInterpolator.class); + } + + private void applyInterpolator() { + if (mInterpolator == null || mNativePtr == null) return; + + long ni; + if (isNativeInterpolator(mInterpolator)) { + ni = ((NativeInterpolator) mInterpolator).createNativeInterpolator(); + } else { + long duration = nGetDuration(mNativePtr.get()); + ni = FallbackLUTInterpolator.createNativeInterpolator(mInterpolator, duration); + } + nSetInterpolator(mNativePtr.get(), ni); + } + + @Override + public void start() { + if (mTarget == null) { + throw new IllegalStateException("Missing target!"); + } + + if (mState != STATE_PREPARE) { + throw new IllegalStateException("Already started!"); + } + + mState = STATE_DELAYED; + if (mHandler == null) { + mHandler = new Handler(true); + } + applyInterpolator(); + + if (mNativePtr == null) { + // It's dead, immediately cancel + cancel(); + } else if (mStartDelay <= 0 || !mUiThreadHandlesDelay) { + nSetStartDelay(mNativePtr.get(), mStartDelay); + doStart(); + } else { + getHelper().addDelayedAnimation(this); + } + } + + private void doStart() { + // 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. + if (mRenderProperty == RenderNodeAnimator.ALPHA && mViewListener != null) { + mViewListener.onAlphaAnimationStart(mFinalValue); + } + + moveToRunningState(); + + if (mViewListener != null) { + // Kick off a frame to start the process + mViewListener.invalidateParent(false); + } + } + + private void moveToRunningState() { + mState = STATE_RUNNING; + if (mNativePtr != null) { + nStart(mNativePtr.get()); + } + notifyStartListeners(); + } + + private void notifyStartListeners() { + final ArrayList<AnimatorListener> listeners = cloneListeners(); + final int numListeners = listeners == null ? 0 : listeners.size(); + for (int i = 0; i < numListeners; i++) { + listeners.get(i).onAnimationStart(this); + } + } + + @Override + public void cancel() { + if (mState != STATE_PREPARE && mState != STATE_FINISHED) { + if (mState == STATE_DELAYED) { + getHelper().removeDelayedAnimation(this); + moveToRunningState(); + } + + final ArrayList<AnimatorListener> listeners = cloneListeners(); + final int numListeners = listeners == null ? 0 : listeners.size(); + for (int i = 0; i < numListeners; i++) { + listeners.get(i).onAnimationCancel(this); + } + + end(); + } + } + + @Override + public void end() { + if (mState != STATE_FINISHED) { + if (mState < STATE_RUNNING) { + getHelper().removeDelayedAnimation(this); + doStart(); + } + if (mNativePtr != null) { + nEnd(mNativePtr.get()); + if (mViewListener != null) { + // Kick off a frame to flush the state change + mViewListener.invalidateParent(false); + } + } else { + // It's already dead, jump to onFinish + onFinished(); + } + } + } + + @Override + public void pause() { + throw new UnsupportedOperationException(); + } + + @Override + public void resume() { + throw new UnsupportedOperationException(); + } + + /** @hide */ + public void setViewListener(ViewListener listener) { + mViewListener = listener; + } + + /** Sets the animation target to the owning view of the RecordingCanvas */ + public final void setTarget(RecordingCanvas canvas) { + setTarget(canvas.mNode); + } + + /** Sets the node that is to be the target of this animation */ + protected void setTarget(RenderNode node) { + checkMutable(); + if (mTarget != null) { + throw new IllegalStateException("Target already set!"); + } + nSetListener(mNativePtr.get(), this); + mTarget = node; + mTarget.addAnimator(this); + } + + /** Set the start value for the animation */ + public void setStartValue(float startValue) { + checkMutable(); + nSetStartValue(mNativePtr.get(), startValue); + } + + @Override + public void setStartDelay(long startDelay) { + checkMutable(); + if (startDelay < 0) { + throw new IllegalArgumentException("startDelay must be positive; " + startDelay); + } + mUnscaledStartDelay = startDelay; + mStartDelay = (long) (ValueAnimator.getDurationScale() * startDelay); + } + + @Override + public long getStartDelay() { + return mUnscaledStartDelay; + } + + @Override + public RenderNodeAnimator setDuration(long duration) { + checkMutable(); + if (duration < 0) { + throw new IllegalArgumentException("duration must be positive; " + duration); + } + mUnscaledDuration = duration; + nSetDuration(mNativePtr.get(), (long) (duration * ValueAnimator.getDurationScale())); + return this; + } + + @Override + public long getDuration() { + return mUnscaledDuration; + } + + @Override + public long getTotalDuration() { + return mUnscaledDuration + mUnscaledStartDelay; + } + + @Override + public boolean isRunning() { + return mState == STATE_DELAYED || mState == STATE_RUNNING; + } + + @Override + public boolean isStarted() { + return mState != STATE_PREPARE; + } + + @Override + public void setInterpolator(TimeInterpolator interpolator) { + checkMutable(); + mInterpolator = interpolator; + } + + @Override + public TimeInterpolator getInterpolator() { + return mInterpolator; + } + + 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) { + getHelper().removeDelayedAnimation(this); + notifyStartListeners(); + } + mState = STATE_FINISHED; + + final ArrayList<AnimatorListener> listeners = cloneListeners(); + final int numListeners = listeners == null ? 0 : listeners.size(); + for (int i = 0; i < numListeners; i++) { + listeners.get(i).onAnimationEnd(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 + // GC'd + releaseNativePtr(); + } + + private void releaseNativePtr() { + if (mNativePtr != null) { + mNativePtr.release(); + mNativePtr = null; + } + } + + @SuppressWarnings("unchecked") + private ArrayList<AnimatorListener> cloneListeners() { + ArrayList<AnimatorListener> listeners = getListeners(); + if (listeners != null) { + listeners = (ArrayList<AnimatorListener>) listeners.clone(); + } + return listeners; + } + + public long getNativeAnimator() { + return mNativePtr.get(); + } + + /** + * @return true if the animator was started, false if still delayed + */ + private boolean processDelayed(long frameTimeMs) { + if (mStartTime == 0) { + mStartTime = frameTimeMs; + } else if ((frameTimeMs - mStartTime) >= mStartDelay) { + doStart(); + return true; + } + return false; + } + + private static DelayedAnimationHelper getHelper() { + DelayedAnimationHelper helper = sAnimationHelper.get(); + if (helper == null) { + helper = new DelayedAnimationHelper(); + sAnimationHelper.set(helper); + } + return helper; + } + + private static ThreadLocal<DelayedAnimationHelper> sAnimationHelper = + new ThreadLocal<DelayedAnimationHelper>(); + + private static class DelayedAnimationHelper implements Runnable { + + private ArrayList<RenderNodeAnimator> mDelayedAnims = new ArrayList<RenderNodeAnimator>(); + private final Choreographer mChoreographer; + private boolean mCallbackScheduled; + + DelayedAnimationHelper() { + mChoreographer = Choreographer.getInstance(); + } + + public void addDelayedAnimation(RenderNodeAnimator animator) { + mDelayedAnims.add(animator); + scheduleCallback(); + } + + public void removeDelayedAnimation(RenderNodeAnimator animator) { + mDelayedAnims.remove(animator); + } + + private void scheduleCallback() { + if (!mCallbackScheduled) { + mCallbackScheduled = true; + mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, this, null); + } + } + + @Override + public void run() { + long frameTimeMs = mChoreographer.getFrameTime(); + mCallbackScheduled = false; + + int end = 0; + for (int i = 0; i < mDelayedAnims.size(); i++) { + RenderNodeAnimator animator = mDelayedAnims.get(i); + if (!animator.processDelayed(frameTimeMs)) { + if (end != i) { + mDelayedAnims.set(end, animator); + } + end++; + } + } + while (mDelayedAnims.size() > end) { + mDelayedAnims.remove(mDelayedAnims.size() - 1); + } + + if (mDelayedAnims.size() > 0) { + scheduleCallback(); + } + } + } + + // Called by native + private static void callOnFinished(RenderNodeAnimator animator) { + if (animator.mHandler != null) { + animator.mHandler.post(animator::onFinished); + } else { + new Handler(Looper.getMainLooper(), null, true).post(animator::onFinished); + } + } + + @Override + public Animator clone() { + throw new IllegalStateException("Cannot clone this animator"); + } + + @Override + public void setAllowRunningAsynchronously(boolean mayRunAsync) { + checkMutable(); + nSetAllowRunningAsync(mNativePtr.get(), mayRunAsync); + } + + private static native long nCreateAnimator(int property, float finalValue); + private static native long nCreateCanvasPropertyFloatAnimator( + long canvasProperty, float finalValue); + private static native long nCreateCanvasPropertyPaintAnimator( + long canvasProperty, int paintField, float finalValue); + private static native long nCreateRevealAnimator( + int x, int y, float startRadius, float endRadius); + + private static native void nSetStartValue(long nativePtr, float startValue); + private static native void nSetDuration(long nativePtr, long duration); + private static native long nGetDuration(long nativePtr); + private static native void nSetStartDelay(long nativePtr, long startDelay); + private static native void nSetInterpolator(long animPtr, long interpolatorPtr); + 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); + private static native void nEnd(long animPtr); +} diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java index 1acf6c512fbd..9fb72cf08b51 100644 --- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java +++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java @@ -42,6 +42,7 @@ import android.graphics.PixelFormat; import android.graphics.RecordingCanvas; import android.graphics.Rect; import android.graphics.RenderNode; +import android.graphics.animation.NativeInterpolatorFactory; import android.os.Build; import android.os.Handler; import android.util.ArrayMap; @@ -54,7 +55,6 @@ import android.util.Property; import android.util.TimeUtils; import android.view.Choreographer; import android.view.NativeVectorDrawableAnimator; -import android.view.RenderNodeAnimatorSetHelper; import android.view.View; import com.android.internal.R; @@ -1532,7 +1532,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { long startDelay = extraDelay + animator.getStartDelay(); TimeInterpolator interpolator = animator.getInterpolator(); long nativeInterpolator = - RenderNodeAnimatorSetHelper.createNativeInterpolator(interpolator, duration); + NativeInterpolatorFactory.createNativeInterpolator(interpolator, duration); startDelay *= ValueAnimator.getDurationScale(); duration *= ValueAnimator.getDurationScale(); @@ -1548,7 +1548,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { * to the last seen RenderNode target and start right away. */ protected void recordLastSeenTarget(RecordingCanvas canvas) { - final RenderNode node = RenderNodeAnimatorSetHelper.getTarget(canvas); + final RenderNode node = canvas.mNode; mLastSeenTarget = new WeakReference<RenderNode>(node); // Add the animator to the list of animators on every draw if (mInitialized || mPendingAnimationActions.size() > 0) { diff --git a/graphics/java/android/graphics/drawable/RippleForeground.java b/graphics/java/android/graphics/drawable/RippleForeground.java index cce9ba31929f..0f376957c8ff 100644 --- a/graphics/java/android/graphics/drawable/RippleForeground.java +++ b/graphics/java/android/graphics/drawable/RippleForeground.java @@ -25,9 +25,9 @@ import android.graphics.CanvasProperty; import android.graphics.Paint; import android.graphics.RecordingCanvas; import android.graphics.Rect; +import android.graphics.animation.RenderNodeAnimator; import android.util.FloatProperty; import android.util.MathUtils; -import android.view.RenderNodeAnimator; import android.view.animation.AnimationUtils; import android.view.animation.LinearInterpolator; import android.view.animation.PathInterpolator; |