Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ad2f8e33 authored by Alan Viverette's avatar Alan Viverette
Browse files

Update ripple behavior, use render thread animation

Change-Id: Ib6bc1e08b05d29606f452961963d58b8fc866746
parent 891e65c5
Loading
Loading
Loading
Loading
+121 −19
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.view;

import android.animation.Animator;
import android.animation.TimeInterpolator;
import android.graphics.Canvas;
import android.graphics.CanvasProperty;
@@ -28,12 +29,12 @@ import com.android.internal.view.animation.HasNativeInterpolator;
import com.android.internal.view.animation.NativeInterpolatorFactory;

import java.lang.ref.WeakReference;
import java.util.ArrayList;

/**
 * @hide
 */
public final class RenderNodeAnimator {

public final 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;
@@ -50,6 +51,11 @@ public final class RenderNodeAnimator {

    // 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;

    // ViewPropertyAnimator uses a mask for its values, we need to remap them
@@ -74,8 +80,11 @@ public final class RenderNodeAnimator {
    private VirtualRefBasePtr mNativePtr;

    private RenderNode mTarget;
    private View mViewTarget;
    private TimeInterpolator mInterpolator;

    private boolean mStarted = false;
    private boolean mFinished = false;

    public int mapViewPropertyToRenderProperty(int viewProperty) {
        return sViewPropertyAnimatorMap.get(viewProperty);
@@ -92,6 +101,14 @@ public final class RenderNodeAnimator {
                property.getNativeContainer(), 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(
                new WeakReference<RenderNodeAnimator>(this),
@@ -115,56 +132,139 @@ public final class RenderNodeAnimator {
        if (mInterpolator.getClass().isAnnotationPresent(HasNativeInterpolator.class)) {
            ni = ((NativeInterpolatorFactory)mInterpolator).createNativeInterpolator();
        } else {
            int duration = nGetDuration(mNativePtr.get());
            long duration = nGetDuration(mNativePtr.get());
            ni = FallbackLUTInterpolator.createNativeInterpolator(mInterpolator, duration);
        }
        nSetInterpolator(mNativePtr.get(), ni);
    }

    private void start(RenderNode node) {
    @Override
    public void start() {
        if (mTarget == null) {
            throw new IllegalStateException("Missing target!");
        }

        if (mStarted) {
            throw new IllegalStateException("Already started!");
        }

        mStarted = true;
        applyInterpolator();
        mTarget = node;
        mTarget.addAnimator(this);

        final ArrayList<AnimatorListener> listeners = getListeners();
        final int numListeners = listeners == null ? 0 : listeners.size();
        for (int i = 0; i < numListeners; i++) {
            listeners.get(i).onAnimationStart(this);
        }

    public void start(View target) {
        start(target.mRenderNode);
        if (mViewTarget != null) {
            // Kick off a frame to start the process
        target.invalidateViewProperty(true, false);
            mViewTarget.invalidateViewProperty(true, false);
        }
    }

    @Override
    public void cancel() {
        mTarget.removeAnimator(this);

        final ArrayList<AnimatorListener> listeners = getListeners();
        final int numListeners = listeners == null ? 0 : listeners.size();
        for (int i = 0; i < numListeners; i++) {
            listeners.get(i).onAnimationCancel(this);
        }
    }

    @Override
    public void end() {
        throw new UnsupportedOperationException();
    }

    @Override
    public void pause() {
        throw new UnsupportedOperationException();
    }

    @Override
    public void resume() {
        throw new UnsupportedOperationException();
    }

    public void start(Canvas canvas) {
    public void setTarget(View view) {
        mViewTarget = view;
        mTarget = view.mRenderNode;
    }

    public void setTarget(Canvas canvas) {
        if (!(canvas instanceof GLES20RecordingCanvas)) {
            throw new IllegalArgumentException("Not a GLES20RecordingCanvas");
        }
        GLES20RecordingCanvas recordingCanvas = (GLES20RecordingCanvas) canvas;
        start(recordingCanvas.mNode);

        final GLES20RecordingCanvas recordingCanvas = (GLES20RecordingCanvas) canvas;
        setTarget(recordingCanvas.mNode);
    }

    public void cancel() {
        mTarget.removeAnimator(this);
    public void setTarget(RenderNode node) {
        mViewTarget = null;
        mTarget = node;
    }

    public RenderNode getTarget() {
        return mTarget;
    }

    @Override
    public void setStartDelay(long startDelay) {
        checkMutable();
        nSetStartDelay(mNativePtr.get(), startDelay);
    }

    @Override
    public long getStartDelay() {
        return nGetStartDelay(mNativePtr.get());
    }

    public void setDuration(int duration) {
    @Override
    public RenderNodeAnimator setDuration(long duration) {
        checkMutable();
        nSetDuration(mNativePtr.get(), duration);
        return this;
    }

    @Override
    public long getDuration() {
        return nGetDuration(mNativePtr.get());
    }

    @Override
    public boolean isRunning() {
        return mStarted && !mFinished;
    }

    @Override
    public void setInterpolator(TimeInterpolator interpolator) {
        checkMutable();
        mInterpolator = interpolator;
    }

    long getNativeAnimator() {
        return mNativePtr.get();
    @Override
    public TimeInterpolator getInterpolator() {
        return mInterpolator;
    }

    private void onFinished() {
        mFinished = true;
        mTarget.removeAnimator(this);

        final ArrayList<AnimatorListener> listeners = getListeners();
        final int numListeners = listeners == null ? 0 : listeners.size();
        for (int i = 0; i < numListeners; i++) {
            listeners.get(i).onAnimationEnd(this);
        }
    }

    long getNativeAnimator() {
        return mNativePtr.get();
    }

    // Called by native
@@ -181,7 +281,9 @@ public final class RenderNodeAnimator {
            long canvasProperty, float deltaValue);
    private static native long nCreateCanvasPropertyPaintAnimator(WeakReference<RenderNodeAnimator> weakThis,
            long canvasProperty, int paintField, float deltaValue);
    private static native void nSetDuration(long nativePtr, int duration);
    private static native int nGetDuration(long nativePtr);
    private static native void nSetDuration(long nativePtr, long duration);
    private static native long nGetDuration(long nativePtr);
    private static native void nSetStartDelay(long nativePtr, long startDelay);
    private static native long nGetStartDelay(long nativePtr);
    private static native void nSetInterpolator(long animPtr, long interpolatorPtr);
}
+25 −10
Original line number Diff line number Diff line
@@ -4774,8 +4774,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
            }
            manageFocusHotspot(true, oldFocus);
            onFocusChanged(true, direction, previouslyFocusedRect);
            manageFocusHotspot(true, oldFocus);
            refreshDrawableState();
        }
    }
@@ -6751,6 +6751,24 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
    }
    /**
     * Sets the pressed state for this view and provides a touch coordinate for
     * animation hinting.
     *
     * @param pressed Pass true to set the View's internal state to "pressed",
     *            or false to reverts the View's internal state from a
     *            previously set "pressed" state.
     * @param x The x coordinate of the touch that caused the press
     * @param y The y coordinate of the touch that caused the press
     */
    private void setPressed(boolean pressed, float x, float y) {
        if (pressed) {
            setHotspot(R.attr.state_pressed, x, y);
        }
        setPressed(pressed);
    }
    /**
     * Sets the pressed state for this view.
     *
@@ -6769,6 +6787,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            mPrivateFlags &= ~PFLAG_PRESSED;
        }
        if (!pressed) {
            clearHotspot(R.attr.state_pressed);
        }
        if (needsRefresh) {
            refreshDrawableState();
        }
@@ -8993,7 +9015,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        if ((viewFlags & ENABLED_MASK) == DISABLED) {
            if (event.getAction() == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
                clearHotspot(R.attr.state_pressed);
                setPressed(false);
            }
            // A disabled view that is clickable still consumes the touch
@@ -9026,8 +9047,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                            // showed it as pressed.  Make it show the pressed
                            // state now (before scheduling the click) to ensure
                            // the user sees it.
                            setHotspot(R.attr.state_pressed, x, y);
                            setPressed(true);
                            setPressed(true, x, y);
                       }
                        if (!mHasPerformedLongPress) {
@@ -9061,8 +9081,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                        }
                        removeTapCallback();
                    } else {
                        clearHotspot(R.attr.state_pressed);
                    }
                    break;
@@ -9175,7 +9193,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     */
    private void removeUnsetPressCallback() {
        if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
            clearHotspot(R.attr.state_pressed);
            setPressed(false);
            removeCallbacks(mUnsetPressedState);
        }
@@ -19234,8 +19251,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        @Override
        public void run() {
            mPrivateFlags &= ~PFLAG_PREPRESSED;
            setHotspot(R.attr.state_pressed, x, y);
            setPressed(true);
            setPressed(true, x, y);
            checkForLongClick(ViewConfiguration.getTapTimeout());
        }
    }
@@ -19516,7 +19532,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
    private final class UnsetPressedState implements Runnable {
        @Override
        public void run() {
            clearHotspot(R.attr.state_pressed);
            setPressed(false);
        }
    }
+23 −5
Original line number Diff line number Diff line
@@ -666,6 +666,8 @@ public class Switch extends CompoundButton {
            case MotionEvent.ACTION_CANCEL: {
                if (mTouchMode == TOUCH_MODE_DRAGGING) {
                    stopDrag(ev);
                    // Allow super class to handle pressed state, etc.
                    super.onTouchEvent(ev);
                    return true;
                }
                mTouchMode = TOUCH_MODE_IDLE;
@@ -801,7 +803,7 @@ public class Switch extends CompoundButton {
    }

    @Override
    protected void onDraw(Canvas canvas) {
    public void draw(Canvas c) {
        final Rect tempRect = mTempRect;
        final Drawable trackDrawable = mTrackDrawable;
        final Drawable thumbDrawable = mThumbDrawable;
@@ -815,9 +817,6 @@ public class Switch extends CompoundButton {
        trackDrawable.getPadding(tempRect);

        final int switchInnerLeft = switchLeft + tempRect.left;
        final int switchInnerTop = switchTop + tempRect.top;
        final int switchInnerRight = switchRight - tempRect.right;
        final int switchInnerBottom = switchBottom - tempRect.bottom;

        // Relies on mTempRect, MUST be called first!
        final int thumbPos = getThumbOffset();
@@ -833,8 +832,26 @@ public class Switch extends CompoundButton {
            background.setHotspotBounds(thumbLeft, switchTop, thumbRight, switchBottom);
        }

        // Draw the background.
        super.draw(c);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        final Rect tempRect = mTempRect;
        final Drawable trackDrawable = mTrackDrawable;
        final Drawable thumbDrawable = mThumbDrawable;
        trackDrawable.getPadding(tempRect);

        final int switchTop = mSwitchTop;
        final int switchBottom = mSwitchBottom;
        final int switchInnerLeft = mSwitchLeft + tempRect.left;
        final int switchInnerTop = switchTop + tempRect.top;
        final int switchInnerRight = mSwitchRight - tempRect.right;
        final int switchInnerBottom = switchBottom - tempRect.bottom;

        if (mSplitTrack) {
            final Insets insets = thumbDrawable.getOpticalInsets();
            thumbDrawable.copyBounds(tempRect);
@@ -861,7 +878,8 @@ public class Switch extends CompoundButton {
            }
            mTextPaint.drawableState = drawableState;

            final int left = (thumbLeft + thumbRight) / 2 - switchText.getWidth() / 2;
            final Rect thumbBounds = thumbDrawable.getBounds();
            final int left = (thumbBounds.left + thumbBounds.right) / 2 - switchText.getWidth() / 2;
            final int top = (switchInnerTop + switchInnerBottom) / 2 - switchText.getHeight() / 2;
            canvas.translate(left, top);
            switchText.draw(canvas);
+3 −3
Original line number Diff line number Diff line
@@ -34,11 +34,11 @@ public class FallbackLUTInterpolator implements NativeInterpolatorFactory {
     * Used to cache the float[] LUT for use across multiple native
     * interpolator creation
     */
    public FallbackLUTInterpolator(TimeInterpolator interpolator, int duration) {
    public FallbackLUTInterpolator(TimeInterpolator interpolator, long duration) {
        mLut = createLUT(interpolator, duration);
    }

    private static float[] createLUT(TimeInterpolator interpolator, int duration) {
    private static float[] createLUT(TimeInterpolator interpolator, long duration) {
        long frameIntervalNanos = Choreographer.getInstance().getFrameIntervalNanos();
        int animIntervalMs = (int) (frameIntervalNanos / TimeUtils.NANOS_PER_MS);
        int numAnimFrames = (int) Math.ceil(duration / animIntervalMs);
@@ -59,7 +59,7 @@ public class FallbackLUTInterpolator implements NativeInterpolatorFactory {
    /**
     * Used to create a one-shot float[] LUT & native interpolator
     */
    public static long createNativeInterpolator(TimeInterpolator interpolator, int duration) {
    public static long createNativeInterpolator(TimeInterpolator interpolator, long duration) {
        float[] lut = createLUT(interpolator, duration);
        return NativeInterpolatorFactoryHelper.createLutInterpolator(lut);
    }
+18 −5
Original line number Diff line number Diff line
@@ -116,15 +116,26 @@ static jlong createCanvasPropertyPaintAnimator(JNIEnv* env, jobject clazz,
    return reinterpret_cast<jlong>( animator );
}

static void setDuration(JNIEnv* env, jobject clazz, jlong animatorPtr, jint duration) {
static void setDuration(JNIEnv* env, jobject clazz, jlong animatorPtr, jlong duration) {
    LOG_ALWAYS_FATAL_IF(duration < 0, "Duration cannot be negative");
    BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr);
    animator->setDuration(duration);
}

static jint getDuration(JNIEnv* env, jobject clazz, jlong animatorPtr) {
static jlong getDuration(JNIEnv* env, jobject clazz, jlong animatorPtr) {
    BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr);
    return static_cast<jint>(animator->duration());
    return static_cast<jlong>(animator->duration());
}

static void setStartDelay(JNIEnv* env, jobject clazz, jlong animatorPtr, jlong startDelay) {
    LOG_ALWAYS_FATAL_IF(startDelay < 0, "Start delay cannot be negative");
    BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr);
    animator->setStartDelay(startDelay);
}

static jlong getStartDelay(JNIEnv* env, jobject clazz, jlong animatorPtr) {
    BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr);
    return static_cast<jlong>(animator->startDelay());
}

static void setInterpolator(JNIEnv* env, jobject clazz, jlong animatorPtr, jlong interpolatorPtr) {
@@ -146,8 +157,10 @@ static JNINativeMethod gMethods[] = {
    { "nCreateAnimator", "(Ljava/lang/ref/WeakReference;IF)J", (void*) createAnimator },
    { "nCreateCanvasPropertyFloatAnimator", "(Ljava/lang/ref/WeakReference;JF)J", (void*) createCanvasPropertyFloatAnimator },
    { "nCreateCanvasPropertyPaintAnimator", "(Ljava/lang/ref/WeakReference;JIF)J", (void*) createCanvasPropertyPaintAnimator },
    { "nSetDuration", "(JI)V", (void*) setDuration },
    { "nGetDuration", "(J)I", (void*) getDuration },
    { "nSetDuration", "(JJ)V", (void*) setDuration },
    { "nGetDuration", "(J)J", (void*) getDuration },
    { "nSetStartDelay", "(JJ)V", (void*) setStartDelay },
    { "nGetStartDelay", "(J)J", (void*) getStartDelay },
    { "nSetInterpolator", "(JJ)V", (void*) setInterpolator },
#endif
};
Loading