diff options
27 files changed, 687 insertions, 655 deletions
diff --git a/core/java/android/view/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java index 0c1edac6608c..31fdfb7489b4 100644 --- a/core/java/android/view/RenderNodeAnimator.java +++ b/core/java/android/view/RenderNodeAnimator.java @@ -16,518 +16,52 @@ package android.view; -import android.animation.Animator; -import android.animation.TimeInterpolator; -import android.animation.ValueAnimator; +import android.annotation.NonNull; 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.util.SparseIntArray; - -import com.android.internal.util.VirtualRefBasePtr; -import com.android.internal.view.animation.FallbackLUTInterpolator; -import com.android.internal.view.animation.HasNativeInterpolator; -import com.android.internal.view.animation.NativeInterpolatorFactory; - -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; +public class RenderNodeAnimator extends android.graphics.animation.RenderNodeAnimator + implements android.graphics.animation.RenderNodeAnimator.ViewListener { - // ViewPropertyAnimator uses a mask for its values, we need to remap them - // to the enum values here. RenderPropertyAnimator can't use the mask values - // directly as internally it uses a lookup table so it needs the values to - // be sequential starting from 0 - private static final SparseIntArray sViewPropertyAnimatorMap = new SparseIntArray(15) {{ - put(ViewPropertyAnimator.TRANSLATION_X, TRANSLATION_X); - put(ViewPropertyAnimator.TRANSLATION_Y, TRANSLATION_Y); - put(ViewPropertyAnimator.TRANSLATION_Z, TRANSLATION_Z); - put(ViewPropertyAnimator.SCALE_X, SCALE_X); - put(ViewPropertyAnimator.SCALE_Y, SCALE_Y); - put(ViewPropertyAnimator.ROTATION, ROTATION); - put(ViewPropertyAnimator.ROTATION_X, ROTATION_X); - put(ViewPropertyAnimator.ROTATION_Y, ROTATION_Y); - put(ViewPropertyAnimator.X, X); - put(ViewPropertyAnimator.Y, Y); - put(ViewPropertyAnimator.Z, Z); - put(ViewPropertyAnimator.ALPHA, ALPHA); - }}; - - private VirtualRefBasePtr mNativePtr; - - private Handler mHandler; - private RenderNode mTarget; private View mViewTarget; - 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; - - public static int mapViewPropertyToRenderProperty(int viewProperty) { - return sViewPropertyAnimatorMap.get(viewProperty); - } public RenderNodeAnimator(int property, float finalValue) { - mRenderProperty = property; - mFinalValue = finalValue; - mUiThreadHandlesDelay = true; - init(nCreateAnimator(property, finalValue)); + super(property, finalValue); } public RenderNodeAnimator(CanvasProperty<Float> property, float finalValue) { - init(nCreateCanvasPropertyFloatAnimator( - property.getNativeContainer(), finalValue)); - mUiThreadHandlesDelay = false; + super(property, finalValue); } - /** - * 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; + super(property, paintField, finalValue); } 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 = ((NativeInterpolatorFactory)mInterpolator).createNativeInterpolator(); - } else { - long duration = nGetDuration(mNativePtr.get()); - ni = FallbackLUTInterpolator.createNativeInterpolator(mInterpolator, duration); - } - nSetInterpolator(mNativePtr.get(), ni); + super(x, y, startRadius, endRadius); } @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() { + public void onAlphaAnimationStart(float finalAlpha) { // 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) { - mViewTarget.ensureTransformationInfo(); - mViewTarget.setAlphaInternal(mFinalValue); - } - - moveToRunningState(); - - if (mViewTarget != null) { - // Kick off a frame to start the process - mViewTarget.invalidateViewProperty(true, 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 (mViewTarget != null) { - // Kick off a frame to flush the state change - mViewTarget.invalidateViewProperty(true, false); - } - } else { - // It's already dead, jump to onFinish - onFinished(); - } - } + mViewTarget.ensureTransformationInfo(); + mViewTarget.setAlphaInternal(finalAlpha); } @Override - public void pause() { - throw new UnsupportedOperationException(); - } - - @Override - public void resume() { - throw new UnsupportedOperationException(); + public void invalidateParent(boolean forceRedraw) { + mViewTarget.invalidateViewProperty(true, false); } /** @hide */ - public void setTarget(View view) { + public void setTarget(@NonNull View view) { mViewTarget = view; + setViewListener(this); setTarget(mViewTarget.mRenderNode); } - - /** Sets the animation target to the owning view of the RecordingCanvas */ - public void setTarget(RecordingCanvas canvas) { - setTarget(canvas.mNode); - } - - /** @hide */ - public void setTarget(DisplayListCanvas canvas) { - setTarget((RecordingCanvas) canvas); - } - - private void setTarget(RenderNode node) { - checkMutable(); - if (mTarget != null) { - throw new IllegalStateException("Target already set!"); - } - nSetListener(mNativePtr.get(), this); - mTarget = node; - mTarget.addAnimator(this); - } - - 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; - - public 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/core/java/android/view/RenderNodeAnimatorSetHelper.java b/core/java/android/view/RenderNodeAnimatorSetHelper.java deleted file mode 100644 index d222e0739fa2..000000000000 --- a/core/java/android/view/RenderNodeAnimatorSetHelper.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2016 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.view; - -import android.animation.TimeInterpolator; -import android.graphics.RecordingCanvas; -import android.graphics.RenderNode; - -import com.android.internal.view.animation.FallbackLUTInterpolator; -import com.android.internal.view.animation.NativeInterpolatorFactory; -import com.android.internal.view.animation.NativeInterpolatorFactoryHelper; - -/** - * This is a helper class to get access to methods and fields needed for RenderNodeAnimatorSet - * that are internal or package private to android.view package. - * - * @hide - */ -public class RenderNodeAnimatorSetHelper { - - /** checkstyle @hide */ - public static RenderNode getTarget(RecordingCanvas recordingCanvas) { - return recordingCanvas.mNode; - } - - /** checkstyle @hide */ - public static long createNativeInterpolator(TimeInterpolator interpolator, long - duration) { - if (interpolator == null) { - // create LinearInterpolator - return NativeInterpolatorFactoryHelper.createLinearInterpolator(); - } else if (RenderNodeAnimator.isNativeInterpolator(interpolator)) { - return ((NativeInterpolatorFactory)interpolator).createNativeInterpolator(); - } else { - return FallbackLUTInterpolator.createNativeInterpolator(interpolator, duration); - } - } - -} diff --git a/core/java/android/view/animation/AccelerateDecelerateInterpolator.java b/core/java/android/view/animation/AccelerateDecelerateInterpolator.java index 21d5a5b86bf2..a2bbc5c3ae9e 100644 --- a/core/java/android/view/animation/AccelerateDecelerateInterpolator.java +++ b/core/java/android/view/animation/AccelerateDecelerateInterpolator.java @@ -17,19 +17,18 @@ package android.view.animation; import android.content.Context; +import android.graphics.animation.HasNativeInterpolator; +import android.graphics.animation.NativeInterpolator; +import android.graphics.animation.NativeInterpolatorFactory; import android.util.AttributeSet; -import com.android.internal.view.animation.HasNativeInterpolator; -import com.android.internal.view.animation.NativeInterpolatorFactory; -import com.android.internal.view.animation.NativeInterpolatorFactoryHelper; - /** * An interpolator where the rate of change starts and ends slowly but * accelerates through the middle. */ @HasNativeInterpolator public class AccelerateDecelerateInterpolator extends BaseInterpolator - implements NativeInterpolatorFactory { + implements NativeInterpolator { public AccelerateDecelerateInterpolator() { } @@ -44,6 +43,6 @@ public class AccelerateDecelerateInterpolator extends BaseInterpolator /** @hide */ @Override public long createNativeInterpolator() { - return NativeInterpolatorFactoryHelper.createAccelerateDecelerateInterpolator(); + return NativeInterpolatorFactory.createAccelerateDecelerateInterpolator(); } } diff --git a/core/java/android/view/animation/AccelerateInterpolator.java b/core/java/android/view/animation/AccelerateInterpolator.java index 6c8d7b19fb15..9d4cd329d6fd 100644 --- a/core/java/android/view/animation/AccelerateInterpolator.java +++ b/core/java/android/view/animation/AccelerateInterpolator.java @@ -20,12 +20,12 @@ import android.content.Context; import android.content.res.Resources; import android.content.res.Resources.Theme; import android.content.res.TypedArray; +import android.graphics.animation.HasNativeInterpolator; +import android.graphics.animation.NativeInterpolator; +import android.graphics.animation.NativeInterpolatorFactory; import android.util.AttributeSet; import com.android.internal.R; -import com.android.internal.view.animation.HasNativeInterpolator; -import com.android.internal.view.animation.NativeInterpolatorFactory; -import com.android.internal.view.animation.NativeInterpolatorFactoryHelper; /** * An interpolator where the rate of change starts out slowly and @@ -33,7 +33,7 @@ import com.android.internal.view.animation.NativeInterpolatorFactoryHelper; * */ @HasNativeInterpolator -public class AccelerateInterpolator extends BaseInterpolator implements NativeInterpolatorFactory { +public class AccelerateInterpolator extends BaseInterpolator implements NativeInterpolator { private final float mFactor; private final double mDoubleFactor; @@ -85,6 +85,6 @@ public class AccelerateInterpolator extends BaseInterpolator implements NativeIn /** @hide */ @Override public long createNativeInterpolator() { - return NativeInterpolatorFactoryHelper.createAccelerateInterpolator(mFactor); + return NativeInterpolatorFactory.createAccelerateInterpolator(mFactor); } } diff --git a/core/java/android/view/animation/AnticipateInterpolator.java b/core/java/android/view/animation/AnticipateInterpolator.java index 7a837c37810c..d14639476d13 100644 --- a/core/java/android/view/animation/AnticipateInterpolator.java +++ b/core/java/android/view/animation/AnticipateInterpolator.java @@ -20,18 +20,18 @@ import android.content.Context; import android.content.res.Resources; import android.content.res.Resources.Theme; import android.content.res.TypedArray; +import android.graphics.animation.HasNativeInterpolator; +import android.graphics.animation.NativeInterpolator; +import android.graphics.animation.NativeInterpolatorFactory; import android.util.AttributeSet; import com.android.internal.R; -import com.android.internal.view.animation.HasNativeInterpolator; -import com.android.internal.view.animation.NativeInterpolatorFactory; -import com.android.internal.view.animation.NativeInterpolatorFactoryHelper; /** * An interpolator where the change starts backward then flings forward. */ @HasNativeInterpolator -public class AnticipateInterpolator extends BaseInterpolator implements NativeInterpolatorFactory { +public class AnticipateInterpolator extends BaseInterpolator implements NativeInterpolator { private final float mTension; public AnticipateInterpolator() { @@ -73,6 +73,6 @@ public class AnticipateInterpolator extends BaseInterpolator implements NativeIn /** @hide */ @Override public long createNativeInterpolator() { - return NativeInterpolatorFactoryHelper.createAnticipateInterpolator(mTension); + return NativeInterpolatorFactory.createAnticipateInterpolator(mTension); } } diff --git a/core/java/android/view/animation/AnticipateOvershootInterpolator.java b/core/java/android/view/animation/AnticipateOvershootInterpolator.java index 9a75134a0c21..4d6a390c0490 100644 --- a/core/java/android/view/animation/AnticipateOvershootInterpolator.java +++ b/core/java/android/view/animation/AnticipateOvershootInterpolator.java @@ -24,11 +24,11 @@ import android.content.Context; import android.content.res.Resources; import android.content.res.Resources.Theme; import android.content.res.TypedArray; +import android.graphics.animation.HasNativeInterpolator; +import android.graphics.animation.NativeInterpolator; +import android.graphics.animation.NativeInterpolatorFactory; import android.util.AttributeSet; -import com.android.internal.view.animation.HasNativeInterpolator; -import com.android.internal.view.animation.NativeInterpolatorFactory; -import com.android.internal.view.animation.NativeInterpolatorFactoryHelper; /** * An interpolator where the change starts backward then flings forward and overshoots @@ -36,7 +36,7 @@ import com.android.internal.view.animation.NativeInterpolatorFactoryHelper; */ @HasNativeInterpolator public class AnticipateOvershootInterpolator extends BaseInterpolator - implements NativeInterpolatorFactory { + implements NativeInterpolator { private final float mTension; public AnticipateOvershootInterpolator() { @@ -103,6 +103,6 @@ public class AnticipateOvershootInterpolator extends BaseInterpolator /** @hide */ @Override public long createNativeInterpolator() { - return NativeInterpolatorFactoryHelper.createAnticipateOvershootInterpolator(mTension); + return NativeInterpolatorFactory.createAnticipateOvershootInterpolator(mTension); } } diff --git a/core/java/android/view/animation/BounceInterpolator.java b/core/java/android/view/animation/BounceInterpolator.java index 909eaa4c7c26..d3f6a3f6806f 100644 --- a/core/java/android/view/animation/BounceInterpolator.java +++ b/core/java/android/view/animation/BounceInterpolator.java @@ -17,17 +17,16 @@ package android.view.animation; import android.content.Context; +import android.graphics.animation.HasNativeInterpolator; +import android.graphics.animation.NativeInterpolator; +import android.graphics.animation.NativeInterpolatorFactory; import android.util.AttributeSet; -import com.android.internal.view.animation.HasNativeInterpolator; -import com.android.internal.view.animation.NativeInterpolatorFactory; -import com.android.internal.view.animation.NativeInterpolatorFactoryHelper; - /** * An interpolator where the change bounces at the end. */ @HasNativeInterpolator -public class BounceInterpolator extends BaseInterpolator implements NativeInterpolatorFactory { +public class BounceInterpolator extends BaseInterpolator implements NativeInterpolator { public BounceInterpolator() { } @@ -56,6 +55,6 @@ public class BounceInterpolator extends BaseInterpolator implements NativeInterp /** @hide */ @Override public long createNativeInterpolator() { - return NativeInterpolatorFactoryHelper.createBounceInterpolator(); + return NativeInterpolatorFactory.createBounceInterpolator(); } }
\ No newline at end of file diff --git a/core/java/android/view/animation/CycleInterpolator.java b/core/java/android/view/animation/CycleInterpolator.java index 72d64a16393a..6b1a80a6baec 100644 --- a/core/java/android/view/animation/CycleInterpolator.java +++ b/core/java/android/view/animation/CycleInterpolator.java @@ -20,12 +20,12 @@ import android.content.Context; import android.content.res.Resources; import android.content.res.Resources.Theme; import android.content.res.TypedArray; +import android.graphics.animation.HasNativeInterpolator; +import android.graphics.animation.NativeInterpolator; +import android.graphics.animation.NativeInterpolatorFactory; import android.util.AttributeSet; import com.android.internal.R; -import com.android.internal.view.animation.HasNativeInterpolator; -import com.android.internal.view.animation.NativeInterpolatorFactory; -import com.android.internal.view.animation.NativeInterpolatorFactoryHelper; /** * Repeats the animation for a specified number of cycles. The @@ -33,7 +33,7 @@ import com.android.internal.view.animation.NativeInterpolatorFactoryHelper; * */ @HasNativeInterpolator -public class CycleInterpolator extends BaseInterpolator implements NativeInterpolatorFactory { +public class CycleInterpolator extends BaseInterpolator implements NativeInterpolator { public CycleInterpolator(float cycles) { mCycles = cycles; } @@ -65,6 +65,6 @@ public class CycleInterpolator extends BaseInterpolator implements NativeInterpo /** @hide */ @Override public long createNativeInterpolator() { - return NativeInterpolatorFactoryHelper.createCycleInterpolator(mCycles); + return NativeInterpolatorFactory.createCycleInterpolator(mCycles); } } diff --git a/core/java/android/view/animation/DecelerateInterpolator.java b/core/java/android/view/animation/DecelerateInterpolator.java index 2d1249df4fb5..2d2f77007bb8 100644 --- a/core/java/android/view/animation/DecelerateInterpolator.java +++ b/core/java/android/view/animation/DecelerateInterpolator.java @@ -20,12 +20,12 @@ import android.content.Context; import android.content.res.Resources; import android.content.res.Resources.Theme; import android.content.res.TypedArray; +import android.graphics.animation.HasNativeInterpolator; +import android.graphics.animation.NativeInterpolator; +import android.graphics.animation.NativeInterpolatorFactory; import android.util.AttributeSet; import com.android.internal.R; -import com.android.internal.view.animation.HasNativeInterpolator; -import com.android.internal.view.animation.NativeInterpolatorFactory; -import com.android.internal.view.animation.NativeInterpolatorFactoryHelper; /** * An interpolator where the rate of change starts out quickly and @@ -33,7 +33,7 @@ import com.android.internal.view.animation.NativeInterpolatorFactoryHelper; * */ @HasNativeInterpolator -public class DecelerateInterpolator extends BaseInterpolator implements NativeInterpolatorFactory { +public class DecelerateInterpolator extends BaseInterpolator implements NativeInterpolator { public DecelerateInterpolator() { } @@ -81,6 +81,6 @@ public class DecelerateInterpolator extends BaseInterpolator implements NativeIn /** @hide */ @Override public long createNativeInterpolator() { - return NativeInterpolatorFactoryHelper.createDecelerateInterpolator(mFactor); + return NativeInterpolatorFactory.createDecelerateInterpolator(mFactor); } } diff --git a/core/java/android/view/animation/LinearInterpolator.java b/core/java/android/view/animation/LinearInterpolator.java index 2a047b48cfb0..f6a820ca5f1c 100644 --- a/core/java/android/view/animation/LinearInterpolator.java +++ b/core/java/android/view/animation/LinearInterpolator.java @@ -17,17 +17,16 @@ package android.view.animation; import android.content.Context; +import android.graphics.animation.HasNativeInterpolator; +import android.graphics.animation.NativeInterpolator; +import android.graphics.animation.NativeInterpolatorFactory; import android.util.AttributeSet; -import com.android.internal.view.animation.HasNativeInterpolator; -import com.android.internal.view.animation.NativeInterpolatorFactory; -import com.android.internal.view.animation.NativeInterpolatorFactoryHelper; - /** * An interpolator where the rate of change is constant */ @HasNativeInterpolator -public class LinearInterpolator extends BaseInterpolator implements NativeInterpolatorFactory { +public class LinearInterpolator extends BaseInterpolator implements NativeInterpolator { public LinearInterpolator() { } @@ -42,6 +41,6 @@ public class LinearInterpolator extends BaseInterpolator implements NativeInterp /** @hide */ @Override public long createNativeInterpolator() { - return NativeInterpolatorFactoryHelper.createLinearInterpolator(); + return NativeInterpolatorFactory.createLinearInterpolator(); } } diff --git a/core/java/android/view/animation/OvershootInterpolator.java b/core/java/android/view/animation/OvershootInterpolator.java index 306688a1b10b..e6445d7397b0 100644 --- a/core/java/android/view/animation/OvershootInterpolator.java +++ b/core/java/android/view/animation/OvershootInterpolator.java @@ -20,19 +20,19 @@ import android.content.Context; import android.content.res.Resources; import android.content.res.Resources.Theme; import android.content.res.TypedArray; +import android.graphics.animation.HasNativeInterpolator; +import android.graphics.animation.NativeInterpolator; +import android.graphics.animation.NativeInterpolatorFactory; import android.util.AttributeSet; import com.android.internal.R; -import com.android.internal.view.animation.HasNativeInterpolator; -import com.android.internal.view.animation.NativeInterpolatorFactory; -import com.android.internal.view.animation.NativeInterpolatorFactoryHelper; /** * An interpolator where the change flings forward and overshoots the last value * then comes back. */ @HasNativeInterpolator -public class OvershootInterpolator extends BaseInterpolator implements NativeInterpolatorFactory { +public class OvershootInterpolator extends BaseInterpolator implements NativeInterpolator { private final float mTension; public OvershootInterpolator() { @@ -76,6 +76,6 @@ public class OvershootInterpolator extends BaseInterpolator implements NativeInt /** @hide */ @Override public long createNativeInterpolator() { - return NativeInterpolatorFactoryHelper.createOvershootInterpolator(mTension); + return NativeInterpolatorFactory.createOvershootInterpolator(mTension); } } diff --git a/core/java/android/view/animation/PathInterpolator.java b/core/java/android/view/animation/PathInterpolator.java index 924437a2a6d4..99d6b9c54c20 100644 --- a/core/java/android/view/animation/PathInterpolator.java +++ b/core/java/android/view/animation/PathInterpolator.java @@ -20,14 +20,14 @@ import android.content.res.Resources; import android.content.res.Resources.Theme; import android.content.res.TypedArray; import android.graphics.Path; +import android.graphics.animation.HasNativeInterpolator; +import android.graphics.animation.NativeInterpolator; +import android.graphics.animation.NativeInterpolatorFactory; import android.util.AttributeSet; import android.util.PathParser; import android.view.InflateException; import com.android.internal.R; -import com.android.internal.view.animation.HasNativeInterpolator; -import com.android.internal.view.animation.NativeInterpolatorFactory; -import com.android.internal.view.animation.NativeInterpolatorFactoryHelper; /** * An interpolator that can traverse a Path that extends from <code>Point</code> @@ -46,7 +46,7 @@ import com.android.internal.view.animation.NativeInterpolatorFactoryHelper; * </pre></blockquote></p> */ @HasNativeInterpolator -public class PathInterpolator extends BaseInterpolator implements NativeInterpolatorFactory { +public class PathInterpolator extends BaseInterpolator implements NativeInterpolator { // This governs how accurate the approximation of the Path is. private static final float PRECISION = 0.002f; @@ -237,7 +237,7 @@ public class PathInterpolator extends BaseInterpolator implements NativeInterpol /** @hide **/ @Override public long createNativeInterpolator() { - return NativeInterpolatorFactoryHelper.createPathInterpolator(mX, mY); + return NativeInterpolatorFactory.createPathInterpolator(mX, mY); } } diff --git a/core/java/com/android/internal/view/animation/NativeInterpolatorFactoryHelper.java b/core/java/com/android/internal/view/animation/NativeInterpolatorFactoryHelper.java deleted file mode 100644 index ebeec40c7083..000000000000 --- a/core/java/com/android/internal/view/animation/NativeInterpolatorFactoryHelper.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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 com.android.internal.view.animation; - -/** - * Static utility class for constructing native interpolators to keep the - * JNI simpler - */ -public final class NativeInterpolatorFactoryHelper { - private NativeInterpolatorFactoryHelper() {} - - public static native long createAccelerateDecelerateInterpolator(); - public static native long createAccelerateInterpolator(float factor); - public static native long createAnticipateInterpolator(float tension); - public static native long createAnticipateOvershootInterpolator(float tension); - public static native long createBounceInterpolator(); - public static native long createCycleInterpolator(float cycles); - public static native long createDecelerateInterpolator(float factor); - public static native long createLinearInterpolator(); - public static native long createOvershootInterpolator(float tension); - public static native long createPathInterpolator(float[] x, float[] y); - public static native long createLutInterpolator(float[] values); -} diff --git a/core/jni/Android.bp b/core/jni/Android.bp index 30d0d1d7d1f6..d1a7d240dfa2 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -42,9 +42,7 @@ cc_library_shared { "android_util_StringBlock.cpp", "android_util_XmlBlock.cpp", "android_util_jar_StrictJarFile.cpp", - "android_view_RenderNodeAnimator.cpp", "com_android_internal_util_VirtualRefBasePtr.cpp", - "com_android_internal_view_animation_NativeInterpolatorFactoryHelper.cpp", ], include_dirs: [ @@ -351,6 +349,8 @@ cc_library_static { "android/graphics/apex/android_paint.cpp", "android/graphics/apex/android_region.cpp", + "android_graphics_animation_NativeInterpolatorFactory.cpp", + "android_graphics_animation_RenderNodeAnimator.cpp", "android_graphics_Canvas.cpp", "android_graphics_ColorSpace.cpp", "android_graphics_drawable_AnimatedVectorDrawable.cpp", diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 19f6e2750219..bbc23fec87ea 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -119,13 +119,11 @@ extern int register_android_graphics_BLASTBufferQueue(JNIEnv* env); extern int register_android_view_DisplayEventReceiver(JNIEnv* env); extern int register_android_view_InputApplicationHandle(JNIEnv* env); extern int register_android_view_InputWindowHandle(JNIEnv* env); -extern int register_android_view_RenderNodeAnimator(JNIEnv* env); extern int register_android_view_Surface(JNIEnv* env); extern int register_android_view_SurfaceControl(JNIEnv* env); extern int register_android_view_SurfaceSession(JNIEnv* env); extern int register_android_view_CompositionSamplingListener(JNIEnv* env); extern int register_android_view_TextureView(JNIEnv* env); -extern int register_com_android_internal_view_animation_NativeInterpolatorFactoryHelper(JNIEnv *env); extern int register_android_database_CursorWindow(JNIEnv* env); extern int register_android_database_SQLiteConnection(JNIEnv* env); extern int register_android_database_SQLiteGlobal(JNIEnv* env); @@ -1461,7 +1459,6 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_os_VintfRuntimeInfo), REG_JNI(register_android_service_DataLoaderService), REG_JNI(register_android_view_DisplayEventReceiver), - REG_JNI(register_android_view_RenderNodeAnimator), REG_JNI(register_android_view_InputApplicationHandle), REG_JNI(register_android_view_InputWindowHandle), REG_JNI(register_android_view_Surface), @@ -1469,7 +1466,6 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_view_SurfaceSession), REG_JNI(register_android_view_CompositionSamplingListener), REG_JNI(register_android_view_TextureView), - REG_JNI(register_com_android_internal_view_animation_NativeInterpolatorFactoryHelper), REG_JNI(register_com_google_android_gles_jni_EGLImpl), REG_JNI(register_com_google_android_gles_jni_GLImpl), REG_JNI(register_android_opengl_jni_EGL14), diff --git a/core/jni/LayoutlibLoader.cpp b/core/jni/LayoutlibLoader.cpp index 7ceef984898d..7ee509b4ecb4 100644 --- a/core/jni/LayoutlibLoader.cpp +++ b/core/jni/LayoutlibLoader.cpp @@ -65,6 +65,8 @@ extern int register_android_graphics_Path(JNIEnv* env); extern int register_android_graphics_PathMeasure(JNIEnv* env); extern int register_android_graphics_Picture(JNIEnv* env); extern int register_android_graphics_Region(JNIEnv* env); +extern int register_android_graphics_animation_NativeInterpolatorFactory(JNIEnv* env); +extern int register_android_graphics_animation_RenderNodeAnimator(JNIEnv* env); extern int register_android_graphics_drawable_AnimatedVectorDrawable(JNIEnv* env); extern int register_android_graphics_drawable_VectorDrawable(JNIEnv* env); extern int register_android_graphics_fonts_Font(JNIEnv* env); @@ -82,10 +84,8 @@ extern int register_android_util_Log(JNIEnv* env); extern int register_android_util_PathParser(JNIEnv* env); extern int register_android_util_jar_StrictJarFile(JNIEnv* env); extern int register_android_view_RenderNode(JNIEnv* env); -extern int register_android_view_RenderNodeAnimator(JNIEnv* env); extern int register_android_view_DisplayListCanvas(JNIEnv* env); extern int register_com_android_internal_util_VirtualRefBasePtr(JNIEnv *env); -extern int register_com_android_internal_view_animation_NativeInterpolatorFactoryHelper(JNIEnv *env); #define REG_JNI(name) { name } struct RegJNIRec { @@ -130,6 +130,10 @@ static const std::unordered_map<std::string, RegJNIRec> gRegJNIMap = { {"android.graphics.Region", REG_JNI(register_android_graphics_Region)}, {"android.graphics.Shader", REG_JNI(register_android_graphics_Shader)}, {"android.graphics.Typeface", REG_JNI(register_android_graphics_Typeface)}, + {"android.graphics.animation.NativeInterpolatorFactory", + REG_JNI(register_android_graphics_animation_NativeInterpolatorFactory)}, + {"android.graphics.animation.RenderNodeAnimator", + REG_JNI(register_android_graphics_animation_RenderNodeAnimator)}, {"android.graphics.drawable.AnimatedVectorDrawable", REG_JNI(register_android_graphics_drawable_AnimatedVectorDrawable)}, {"android.graphics.drawable.VectorDrawable", @@ -151,11 +155,8 @@ static const std::unordered_map<std::string, RegJNIRec> gRegJNIMap = { {"android.util.Log", REG_JNI(register_android_util_Log)}, {"android.util.PathParser", REG_JNI(register_android_util_PathParser)}, {"android.util.jar.StrictJarFile", REG_JNI(register_android_util_jar_StrictJarFile)}, - {"android.view.RenderNodeAnimator", REG_JNI(register_android_view_RenderNodeAnimator)}, {"com.android.internal.util.VirtualRefBasePtr", REG_JNI(register_com_android_internal_util_VirtualRefBasePtr)}, - {"com.android.internal.view.animation.NativeInterpolatorFactoryHelper", - REG_JNI(register_com_android_internal_view_animation_NativeInterpolatorFactoryHelper)}, }; // Vector to store the names of classes that need delegates of their native methods static vector<string> classesToDelegate; diff --git a/core/jni/android/graphics/apex/jni_runtime.cpp b/core/jni/android/graphics/apex/jni_runtime.cpp index 1f661534ad81..35c997d80b61 100644 --- a/core/jni/android/graphics/apex/jni_runtime.cpp +++ b/core/jni/android/graphics/apex/jni_runtime.cpp @@ -60,6 +60,8 @@ extern int register_android_graphics_PathMeasure(JNIEnv* env); extern int register_android_graphics_Picture(JNIEnv*); extern int register_android_graphics_Region(JNIEnv* env); extern int register_android_graphics_SurfaceTexture(JNIEnv* env); +extern int register_android_graphics_animation_NativeInterpolatorFactory(JNIEnv* env); +extern int register_android_graphics_animation_RenderNodeAnimator(JNIEnv* env); extern int register_android_graphics_drawable_AnimatedVectorDrawable(JNIEnv* env); extern int register_android_graphics_drawable_VectorDrawable(JNIEnv* env); extern int register_android_graphics_fonts_Font(JNIEnv* env); @@ -123,6 +125,8 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_graphics_SurfaceTexture), REG_JNI(register_android_graphics_Typeface), REG_JNI(register_android_graphics_YuvImage), + REG_JNI(register_android_graphics_animation_NativeInterpolatorFactory), + REG_JNI(register_android_graphics_animation_RenderNodeAnimator), REG_JNI(register_android_graphics_drawable_AnimatedVectorDrawable), REG_JNI(register_android_graphics_drawable_VectorDrawable), REG_JNI(register_android_graphics_fonts_Font), diff --git a/core/jni/com_android_internal_view_animation_NativeInterpolatorFactoryHelper.cpp b/core/jni/android_graphics_animation_NativeInterpolatorFactory.cpp index f4d2e7ba882b..2073ac2d24be 100644 --- a/core/jni/com_android_internal_view_animation_NativeInterpolatorFactoryHelper.cpp +++ b/core/jni/android_graphics_animation_NativeInterpolatorFactory.cpp @@ -90,7 +90,7 @@ static jlong createLutInterpolator(JNIEnv* env, jobject clazz, jfloatArray jlut) // JNI Glue // ---------------------------------------------------------------------------- -const char* const kClassPathName = "com/android/internal/view/animation/NativeInterpolatorFactoryHelper"; +const char* const kClassPathName = "android/graphics/animation/NativeInterpolatorFactory"; static const JNINativeMethod gMethods[] = { { "createAccelerateDecelerateInterpolator", "()J", (void*) createAccelerateDecelerateInterpolator }, @@ -106,7 +106,7 @@ static const JNINativeMethod gMethods[] = { { "createLutInterpolator", "([F)J", (void*) createLutInterpolator }, }; -int register_com_android_internal_view_animation_NativeInterpolatorFactoryHelper(JNIEnv* env) { +int register_android_graphics_animation_NativeInterpolatorFactory(JNIEnv* env) { return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods)); } diff --git a/core/jni/android_view_RenderNodeAnimator.cpp b/core/jni/android_graphics_animation_RenderNodeAnimator.cpp index ca32b0051bf5..878d4fc13f6d 100644 --- a/core/jni/android_view_RenderNodeAnimator.cpp +++ b/core/jni/android_graphics_animation_RenderNodeAnimator.cpp @@ -190,7 +190,7 @@ static void end(JNIEnv* env, jobject clazz, jlong animatorPtr) { // JNI Glue // ---------------------------------------------------------------------------- -const char* const kClassPathName = "android/view/RenderNodeAnimator"; +const char* const kClassPathName = "android/graphics/animation/RenderNodeAnimator"; static const JNINativeMethod gMethods[] = { { "nCreateAnimator", "(IF)J", (void*) createAnimator }, @@ -203,12 +203,12 @@ static const JNINativeMethod gMethods[] = { { "nSetStartDelay", "(JJ)V", (void*) setStartDelay }, { "nSetInterpolator", "(JJ)V", (void*) setInterpolator }, { "nSetAllowRunningAsync", "(JZ)V", (void*) setAllowRunningAsync }, - { "nSetListener", "(JLandroid/view/RenderNodeAnimator;)V", (void*) setListener}, + { "nSetListener", "(JLandroid/graphics/animation/RenderNodeAnimator;)V", (void*) setListener}, { "nStart", "(J)V", (void*) start}, { "nEnd", "(J)V", (void*) end }, }; -int register_android_view_RenderNodeAnimator(JNIEnv* env) { +int register_android_graphics_animation_RenderNodeAnimator(JNIEnv* env) { sLifecycleChecker.incStrong(0); gRenderNodeAnimatorClassInfo.clazz = FindClassOrDie(env, kClassPathName); gRenderNodeAnimatorClassInfo.clazz = MakeGlobalRefOrDie(env, @@ -216,7 +216,7 @@ int register_android_view_RenderNodeAnimator(JNIEnv* env) { gRenderNodeAnimatorClassInfo.callOnFinished = GetStaticMethodIDOrDie( env, gRenderNodeAnimatorClassInfo.clazz, "callOnFinished", - "(Landroid/view/RenderNodeAnimator;)V"); + "(Landroid/graphics/animation/RenderNodeAnimator;)V"); return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods)); } 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/core/java/com/android/internal/view/animation/FallbackLUTInterpolator.java b/graphics/java/android/graphics/animation/FallbackLUTInterpolator.java index d28ab078d74a..36062c141ed2 100644 --- a/core/java/com/android/internal/view/animation/FallbackLUTInterpolator.java +++ b/graphics/java/android/graphics/animation/FallbackLUTInterpolator.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.internal.view.animation; +package android.graphics.animation; import android.animation.TimeInterpolator; import android.util.TimeUtils; @@ -26,14 +26,15 @@ import android.view.Choreographer; * with {@link HasNativeInterpolator} * * This implements TimeInterpolator to allow for easier interop with Animators + * @hide */ @HasNativeInterpolator -public class FallbackLUTInterpolator implements NativeInterpolatorFactory, TimeInterpolator { +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[]; + private final float[] mLut; /** * Used to cache the float[] LUT for use across multiple native @@ -50,7 +51,7 @@ public class FallbackLUTInterpolator implements NativeInterpolatorFactory, TimeI // 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[] values = new float[numAnimFrames]; float lastFrame = numAnimFrames - 1; for (int i = 0; i < numAnimFrames; i++) { float inValue = i / lastFrame; @@ -61,7 +62,7 @@ public class FallbackLUTInterpolator implements NativeInterpolatorFactory, TimeI @Override public long createNativeInterpolator() { - return NativeInterpolatorFactoryHelper.createLutInterpolator(mLut); + return NativeInterpolatorFactory.createLutInterpolator(mLut); } /** @@ -69,7 +70,7 @@ public class FallbackLUTInterpolator implements NativeInterpolatorFactory, TimeI */ public static long createNativeInterpolator(TimeInterpolator interpolator, long duration) { float[] lut = createLUT(interpolator, duration); - return NativeInterpolatorFactoryHelper.createLutInterpolator(lut); + return NativeInterpolatorFactory.createLutInterpolator(lut); } @Override diff --git a/core/java/com/android/internal/view/animation/HasNativeInterpolator.java b/graphics/java/android/graphics/animation/HasNativeInterpolator.java index 48ea4da9a025..c53d5a42524d 100644 --- a/core/java/com/android/internal/view/animation/HasNativeInterpolator.java +++ b/graphics/java/android/graphics/animation/HasNativeInterpolator.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.internal.view.animation; +package android.graphics.animation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -23,10 +23,10 @@ import java.lang.annotation.Target; /** * This is a class annotation that signals that it is safe to create - * a native interpolator counterpart via {@link NativeInterpolatorFactory} + * a native interpolator counterpart via {@link NativeInterpolator} * * The idea here is to prevent subclasses of interpolators from being treated as a - * NativeInterpolatorFactory, and instead have them fall back to the LUT & LERP + * NativeInterpolator, and instead have them fall back to the LUT & LERP * method like a custom interpolator. * * @hide diff --git a/core/java/com/android/internal/view/animation/NativeInterpolatorFactory.java b/graphics/java/android/graphics/animation/NativeInterpolator.java index fcacd52ca398..1e6fea8da466 100644 --- a/core/java/com/android/internal/view/animation/NativeInterpolatorFactory.java +++ b/graphics/java/android/graphics/animation/NativeInterpolator.java @@ -14,8 +14,16 @@ * limitations under the License. */ -package com.android.internal.view.animation; +package android.graphics.animation; -public interface NativeInterpolatorFactory { +/** + * @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; |