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

Commit 28cfd20f authored by Doris Liu's avatar Doris Liu
Browse files

Support running AVD on UI thread

By default, AVD animates on RT thread. But since in some cases there's a
need for a finer control on when the frame update for the animation should
happen, such as coordiating the AVD animation with other animations that
run on UI thread, we are providing a way to force the AVD to run on UI
thread.

Bug: 27278616
Change-Id: I372ecd3dc52e3fa0bdce3a1e9c19443f9b199027
parent 272fe133
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -779,7 +779,7 @@ public class RenderNode {
        return mOwningView != null && mOwningView.mAttachInfo != null;
        return mOwningView != null && mOwningView.mAttachInfo != null;
    }
    }


    public void addAnimator(AnimatedVectorDrawable.VectorDrawableAnimator animatorSet) {
    public void addAnimator(AnimatedVectorDrawable.VectorDrawableAnimatorRT animatorSet) {
        if (mOwningView == null || mOwningView.mAttachInfo == null) {
        if (mOwningView == null || mOwningView.mAttachInfo == null) {
            throw new IllegalStateException("Cannot start this animator on a detached view!");
            throw new IllegalStateException("Cannot start this animator on a detached view!");
        }
        }
+4 −4
Original line number Original line Diff line number Diff line
@@ -175,13 +175,13 @@ static const JNINativeMethod gMethods[] = {
    {"nCreatePathPropertyHolder", "!(JIFF)J", (void*)createPathPropertyHolder},
    {"nCreatePathPropertyHolder", "!(JIFF)J", (void*)createPathPropertyHolder},
    {"nCreateRootAlphaPropertyHolder", "!(JFF)J", (void*)createRootAlphaPropertyHolder},
    {"nCreateRootAlphaPropertyHolder", "!(JFF)J", (void*)createRootAlphaPropertyHolder},
    {"nSetPropertyHolderData", "(J[FI)V", (void*)setPropertyHolderData},
    {"nSetPropertyHolderData", "(J[FI)V", (void*)setPropertyHolderData},
    {"nStart", "(JLandroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator;I)V", (void*)start},
    {"nStart", "(JLandroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimatorRT;I)V", (void*)start},
    {"nReverse", "(JLandroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator;I)V", (void*)reverse},
    {"nReverse", "(JLandroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimatorRT;I)V", (void*)reverse},
    {"nEnd", "!(J)V", (void*)end},
    {"nEnd", "!(J)V", (void*)end},
    {"nReset", "!(J)V", (void*)reset},
    {"nReset", "!(J)V", (void*)reset},
};
};


const char* const kClassPathName = "android/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator";
const char* const kClassPathName = "android/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimatorRT";
int register_android_graphics_drawable_AnimatedVectorDrawable(JNIEnv* env) {
int register_android_graphics_drawable_AnimatedVectorDrawable(JNIEnv* env) {
    gVectorDrawableAnimatorClassInfo.clazz = FindClassOrDie(env, kClassPathName);
    gVectorDrawableAnimatorClassInfo.clazz = FindClassOrDie(env, kClassPathName);
    gVectorDrawableAnimatorClassInfo.clazz = MakeGlobalRefOrDie(env,
    gVectorDrawableAnimatorClassInfo.clazz = MakeGlobalRefOrDie(env,
@@ -189,7 +189,7 @@ int register_android_graphics_drawable_AnimatedVectorDrawable(JNIEnv* env) {


    gVectorDrawableAnimatorClassInfo.callOnFinished = GetStaticMethodIDOrDie(
    gVectorDrawableAnimatorClassInfo.callOnFinished = GetStaticMethodIDOrDie(
            env, gVectorDrawableAnimatorClassInfo.clazz, "callOnFinished",
            env, gVectorDrawableAnimatorClassInfo.clazz, "callOnFinished",
            "(Landroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator;I)V");
            "(Landroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimatorRT;I)V");
    return RegisterMethodsOrDie(env, "android/graphics/drawable/AnimatedVectorDrawable",
    return RegisterMethodsOrDie(env, "android/graphics/drawable/AnimatedVectorDrawable",
            gMethods, NELEM(gMethods));
            gMethods, NELEM(gMethods));
}
}
+148 −25
Original line number Original line Diff line number Diff line
@@ -154,7 +154,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {
    private static final boolean DBG_ANIMATION_VECTOR_DRAWABLE = false;
    private static final boolean DBG_ANIMATION_VECTOR_DRAWABLE = false;


    /** Local, mutable animator set. */
    /** Local, mutable animator set. */
    private final VectorDrawableAnimator mAnimatorSet = new VectorDrawableAnimator(this);
    private VectorDrawableAnimator mAnimatorSet = new VectorDrawableAnimatorRT(this);


    /**
    /**
     * The resources against which this drawable was created. Used to attempt
     * The resources against which this drawable was created. Used to attempt
@@ -164,8 +164,8 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {


    private AnimatedVectorDrawableState mAnimatedVectorState;
    private AnimatedVectorDrawableState mAnimatedVectorState;


    /** Whether the animator set has been prepared. */
    /** The animator set that is parsed from the xml. */
    private boolean mHasAnimatorSet;
    private AnimatorSet mAnimatorSetFromXml = null;


    private boolean mMutated;
    private boolean mMutated;


@@ -234,9 +234,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {


    @Override
    @Override
    public void draw(Canvas canvas) {
    public void draw(Canvas canvas) {
        if (canvas.isHardwareAccelerated()) {
        mAnimatorSet.onDraw(canvas);
            mAnimatorSet.recordLastSeenTarget((DisplayListCanvas) canvas);
        }
        mAnimatedVectorState.mVectorDrawable.draw(canvas);
        mAnimatedVectorState.mVectorDrawable.draw(canvas);
    }
    }


@@ -392,6 +390,24 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {
        mRes = state.mPendingAnims == null ? null : res;
        mRes = state.mPendingAnims == null ? null : res;
    }
    }


    /**
     * Force to animate on UI thread.
     * @hide
     */
    public void forceAnimationOnUI() {
        if (mAnimatorSet instanceof VectorDrawableAnimatorRT) {
            VectorDrawableAnimatorRT animator = (VectorDrawableAnimatorRT) mAnimatorSet;
            if (animator.isRunning()) {
                throw new UnsupportedOperationException("Cannot force Animated Vector Drawable to" +
                        " run on UI thread when the animation has started on RenderThread.");
            }
            mAnimatorSet = new VectorDrawableAnimatorUI(this);
            if (mAnimatorSetFromXml != null) {
                mAnimatorSet.init(mAnimatorSetFromXml);
            }
        }
    }

    @Override
    @Override
    public boolean canApplyTheme() {
    public boolean canApplyTheme() {
        return (mAnimatedVectorState != null && mAnimatedVectorState.canApplyTheme())
        return (mAnimatedVectorState != null && mAnimatedVectorState.canApplyTheme())
@@ -612,6 +628,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {
     * Resets the AnimatedVectorDrawable to the start state as specified in the animators.
     * Resets the AnimatedVectorDrawable to the start state as specified in the animators.
     */
     */
    public void reset() {
    public void reset() {
        ensureAnimatorSet();
        mAnimatorSet.reset();
        mAnimatorSet.reset();
    }
    }


@@ -623,13 +640,12 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {


    @NonNull
    @NonNull
    private void ensureAnimatorSet() {
    private void ensureAnimatorSet() {
        if (!mHasAnimatorSet) {
        if (mAnimatorSetFromXml == null) {
            // TODO: Skip the AnimatorSet creation and init the VectorDrawableAnimator directly
            // TODO: Skip the AnimatorSet creation and init the VectorDrawableAnimator directly
            // with a list of LocalAnimators.
            // with a list of LocalAnimators.
            AnimatorSet set = new AnimatorSet();
            mAnimatorSetFromXml = new AnimatorSet();
            mAnimatedVectorState.prepareLocalAnimators(set, mRes);
            mAnimatedVectorState.prepareLocalAnimators(mAnimatorSetFromXml, mRes);
            mHasAnimatorSet = true;
            mAnimatorSet.init(mAnimatorSetFromXml);
            mAnimatorSet.initWithAnimatorSet(set);
            mRes = null;
            mRes = null;
        }
        }
    }
    }
@@ -724,7 +740,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {
    // A helper function to clean up the animator listener in the mAnimatorSet.
    // A helper function to clean up the animator listener in the mAnimatorSet.
    private void removeAnimatorSetListener() {
    private void removeAnimatorSetListener() {
        if (mAnimatorListener != null) {
        if (mAnimatorListener != null) {
            mAnimatorSet.removeListener();
            mAnimatorSet.removeListener(mAnimatorListener);
            mAnimatorListener = null;
            mAnimatorListener = null;
        }
        }
    }
    }
@@ -754,10 +770,100 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {
        mAnimationCallbacks.clear();
        mAnimationCallbacks.clear();
    }
    }


    private interface VectorDrawableAnimator {
        void init(AnimatorSet set);
        void start();
        void end();
        void reset();
        void reverse();
        boolean canReverse();
        void setListener(AnimatorListener listener);
        void removeListener(AnimatorListener listener);
        void onDraw(Canvas canvas);
        boolean isStarted();
        boolean isRunning();
    }

    private static class VectorDrawableAnimatorUI implements VectorDrawableAnimator {
        private AnimatorSet mSet = new AnimatorSet();
        private final Drawable mDrawable;

        VectorDrawableAnimatorUI(AnimatedVectorDrawable drawable) {
            mDrawable = drawable;
        }

        @Override
        public void init(AnimatorSet set) {
            mSet = set;
        }

        @Override
        public void start() {
            if (mSet.isStarted()) {
                return;
            }
            mSet.start();
            invalidateOwningView();
        }

        @Override
        public void end() {
            mSet.end();
        }

        @Override
        public void reset() {
            start();
            mSet.cancel();
        }

        @Override
        public void reverse() {
            mSet.reverse();
            invalidateOwningView();
        }

        @Override
        public boolean canReverse() {
            return mSet.canReverse();
        }

        @Override
        public void setListener(AnimatorListener listener) {
            mSet.addListener(listener);
        }

        @Override
        public void removeListener(AnimatorListener listener) {
            mSet.removeListener(listener);
        }

        @Override
        public void onDraw(Canvas canvas) {
            if (mSet.isStarted()) {
                invalidateOwningView();
            }
        }

        @Override
        public boolean isStarted() {
            return mSet.isStarted();
        }

        @Override
        public boolean isRunning() {
            return mSet.isRunning();
        }

        private void invalidateOwningView() {
            mDrawable.invalidateSelf();
        }
    }

    /**
    /**
     * @hide
     * @hide
     */
     */
    public static class VectorDrawableAnimator {
    public static class VectorDrawableAnimatorRT implements VectorDrawableAnimator {
        private static final int NONE = 0;
        private static final int NONE = 0;
        private static final int START_ANIMATION = 1;
        private static final int START_ANIMATION = 1;
        private static final int REVERSE_ANIMATION = 2;
        private static final int REVERSE_ANIMATION = 2;
@@ -779,7 +885,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {
        private int mPendingAnimationAction = NONE;
        private int mPendingAnimationAction = NONE;
        private final Drawable mDrawable;
        private final Drawable mDrawable;


        VectorDrawableAnimator(AnimatedVectorDrawable drawable) {
        VectorDrawableAnimatorRT(AnimatedVectorDrawable drawable) {
            mDrawable = drawable;
            mDrawable = drawable;
            mSetPtr = nCreateAnimatorSet();
            mSetPtr = nCreateAnimatorSet();
            // Increment ref count on native AnimatorSet, so it doesn't get released before Java
            // Increment ref count on native AnimatorSet, so it doesn't get released before Java
@@ -787,7 +893,8 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {
            mSetRefBasePtr = new VirtualRefBasePtr(mSetPtr);
            mSetRefBasePtr = new VirtualRefBasePtr(mSetPtr);
        }
        }


        private void initWithAnimatorSet(AnimatorSet set) {
        @Override
        public void init(AnimatorSet set) {
            if (mInitialized) {
            if (mInitialized) {
                // Already initialized
                // Already initialized
                throw new UnsupportedOperationException("VectorDrawableAnimator cannot be " +
                throw new UnsupportedOperationException("VectorDrawableAnimator cannot be " +
@@ -816,7 +923,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {
            ArrayList<Animator> animators = set.getChildAnimations();
            ArrayList<Animator> animators = set.getChildAnimations();


            boolean playTogether = set.shouldPlayTogether();
            boolean playTogether = set.shouldPlayTogether();
            // Convert AnimatorSet to VectorDrawableAnimator
            // Convert AnimatorSet to VectorDrawableAnimatorRT
            for (int i = 0; i < animators.size(); i++) {
            for (int i = 0; i < animators.size(); i++) {
                Animator animator = animators.get(i);
                Animator animator = animators.get(i);
                // Here we only support ObjectAnimator
                // Here we only support ObjectAnimator
@@ -1060,6 +1167,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {
            mDrawable.invalidateSelf();
            mDrawable.invalidateSelf();
        }
        }


        @Override
        public void start() {
        public void start() {
            if (!mInitialized) {
            if (!mInitialized) {
                return;
                return;
@@ -1083,6 +1191,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {
            }
            }
        }
        }


        @Override
        public void end() {
        public void end() {
            if (mInitialized && useLastSeenTarget()) {
            if (mInitialized && useLastSeenTarget()) {
                // If no target has ever been set, no-op
                // If no target has ever been set, no-op
@@ -1091,6 +1200,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {
            }
            }
        }
        }


        @Override
        public void reset() {
        public void reset() {
            if (mInitialized && useLastSeenTarget()) {
            if (mInitialized && useLastSeenTarget()) {
                // If no target has ever been set, no-op
                // If no target has ever been set, no-op
@@ -1101,7 +1211,8 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {


        // Current (imperfect) Java AnimatorSet cannot be reversed when the set contains sequential
        // Current (imperfect) Java AnimatorSet cannot be reversed when the set contains sequential
        // animators or when the animator set has a start delay
        // animators or when the animator set has a start delay
        void reverse() {
        @Override
        public void reverse() {
            if (!mIsReversible || !mInitialized) {
            if (!mIsReversible || !mInitialized) {
                return;
                return;
            }
            }
@@ -1125,29 +1236,41 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {
            return mSetPtr;
            return mSetPtr;
        }
        }


        boolean canReverse() {
        @Override
        public boolean canReverse() {
            return mIsReversible;
            return mIsReversible;
        }
        }


        boolean isStarted() {
        @Override
        public boolean isStarted() {
            return mStarted;
            return mStarted;
        }
        }


        boolean isRunning() {
        @Override
        public boolean isRunning() {
            if (!mInitialized) {
            if (!mInitialized) {
                return false;
                return false;
            }
            }
            return mStarted;
            return mStarted;
        }
        }


        void setListener(AnimatorListener listener) {
        @Override
        public void setListener(AnimatorListener listener) {
            mListener = listener;
            mListener = listener;
        }
        }


        void removeListener() {
        @Override
        public void removeListener(AnimatorListener listener) {
            mListener = null;
            mListener = null;
        }
        }


        @Override
        public void onDraw(Canvas canvas) {
            if (canvas.isHardwareAccelerated()) {
                recordLastSeenTarget((DisplayListCanvas) canvas);
            }
        }

        private void onAnimationEnd(int listenerId) {
        private void onAnimationEnd(int listenerId) {
            if (listenerId != mLastListenerId) {
            if (listenerId != mLastListenerId) {
                return;
                return;
@@ -1162,7 +1285,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {
        }
        }


        // onFinished: should be called from native
        // onFinished: should be called from native
        private static void callOnFinished(VectorDrawableAnimator set, int id) {
        private static void callOnFinished(VectorDrawableAnimatorRT set, int id) {
            set.onAnimationEnd(id);
            set.onAnimationEnd(id);
        }
        }
    }
    }
@@ -1183,8 +1306,8 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {
    private static native long nCreateRootAlphaPropertyHolder(long nativePtr, float startValue,
    private static native long nCreateRootAlphaPropertyHolder(long nativePtr, float startValue,
            float endValue);
            float endValue);
    private static native void nSetPropertyHolderData(long nativePtr, float[] data, int length);
    private static native void nSetPropertyHolderData(long nativePtr, float[] data, int length);
    private static native void nStart(long animatorSetPtr, VectorDrawableAnimator set, int id);
    private static native void nStart(long animatorSetPtr, VectorDrawableAnimatorRT set, int id);
    private static native void nReverse(long animatorSetPtr, VectorDrawableAnimator set, int id);
    private static native void nReverse(long animatorSetPtr, VectorDrawableAnimatorRT set, int id);
    private static native void nEnd(long animatorSetPtr);
    private static native void nEnd(long animatorSetPtr);
    private static native void nReset(long animatorSetPtr);
    private static native void nReset(long animatorSetPtr);
}
}
+1 −1
Original line number Original line Diff line number Diff line
@@ -907,7 +907,7 @@ android.graphics.drawable.AnimatedVectorDrawable
android.graphics.drawable.AnimatedVectorDrawable$1
android.graphics.drawable.AnimatedVectorDrawable$1
android.graphics.drawable.AnimatedVectorDrawable$AnimatedVectorDrawableState
android.graphics.drawable.AnimatedVectorDrawable$AnimatedVectorDrawableState
android.graphics.drawable.AnimatedVectorDrawable$AnimatedVectorDrawableState$PendingAnimator
android.graphics.drawable.AnimatedVectorDrawable$AnimatedVectorDrawableState$PendingAnimator
android.graphics.drawable.AnimatedVectorDrawable$VectorDrawableAnimator
android.graphics.drawable.AnimatedVectorDrawable$VectorDrawableAnimatorRT
android.graphics.drawable.AnimationDrawable
android.graphics.drawable.AnimationDrawable
android.graphics.drawable.AnimationDrawable$AnimationState
android.graphics.drawable.AnimationDrawable$AnimationState
android.graphics.drawable.BitmapDrawable
android.graphics.drawable.BitmapDrawable