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

Commit 62cb534e authored by Alan Viverette's avatar Alan Viverette Committed by Android (Google) Code Review
Browse files

Merge "Update ripple behavior, use render thread animation"

parents 779b59ce ad2f8e33
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