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

Commit ef062ebd authored by Doris Liu's avatar Doris Liu
Browse files

Ref count the nodes in VectorDrawable

Also added API check so that for pre-N we ignore invalid VD animation,
in order to avoid breaking old apps.

Bug: 26975469
Bug: 26949340
Change-Id: I498539ad6a05de3d886e7dcdc8a167e78333ab11
parent 766431aa
Loading
Loading
Loading
Loading
+0 −6
Original line number Diff line number Diff line
@@ -138,11 +138,6 @@ static jlong createGroup(JNIEnv*, jobject, jlong srcGroupPtr) {
    return reinterpret_cast<jlong>(newGroup);
}

static void deleteNode(JNIEnv*, jobject, jlong nodePtr) {
    VectorDrawable::Node* node = reinterpret_cast<VectorDrawable::Node*>(nodePtr);
    delete node;
}

static void setNodeName(JNIEnv* env, jobject, jlong nodePtr, jstring nameStr) {
    VectorDrawable::Node* node = reinterpret_cast<VectorDrawable::Node*>(nodePtr);
    const char* nodeName = env->GetStringUTFChars(nameStr, NULL);
@@ -346,7 +341,6 @@ static const JNINativeMethod gMethods[] = {
        {"nCreateClipPath", "!(J)J", (void*)createClipPath},
        {"nCreateGroup", "!()J", (void*)createEmptyGroup},
        {"nCreateGroup", "!(J)J", (void*)createGroup},
        {"nDestroy", "!(J)V", (void*)deleteNode},
        {"nSetName", "(JLjava/lang/String;)V", (void*)setNodeName},
        {"nUpdateGroupProperties", "!(JFFFFFFF)V", (void*)updateGroupProperties},

+52 −11
Original line number Diff line number Diff line
@@ -25,6 +25,8 @@ import android.animation.ValueAnimator;
import android.animation.ObjectAnimator;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityThread;
import android.app.Application;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.content.res.Resources.Theme;
@@ -35,6 +37,7 @@ import android.graphics.Insets;
import android.graphics.Outline;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.os.Build;
import android.util.ArrayMap;
import android.util.AttributeSet;
import android.util.Log;
@@ -200,6 +203,24 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {
        mMutated = false;
    }

    /**
     * In order to avoid breaking old apps, we only throw exception on invalid VectorDrawable
     * animations * for apps targeting N and later. For older apps, we ignore (i.e. quietly skip)
     * these animations.
     *
     * @return whether invalid animations for vector drawable should be ignored.
     */
    private static boolean shouldIgnoreInvalidAnimation() {
        Application app = ActivityThread.currentApplication();
        if (app == null || app.getApplicationInfo() == null) {
            return true;
        }
        if (app.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.N) {
            return true;
        }
        return false;
    }

    @Override
    public ConstantState getConstantState() {
        mAnimatedVectorState.mChangingConfigurations = getChangingConfigurations();
@@ -763,6 +784,8 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {
        private boolean mInitialized = false;
        private boolean mAnimationPending = false;
        private boolean mIsReversible = false;
        // This needs to be set before parsing starts.
        private boolean mShouldIgnoreInvalidAnim;
        // TODO: Consider using NativeAllocationRegistery to track native allocation
        private final VirtualRefBasePtr mSetRefBasePtr;
        private WeakReference<RenderNode> mTarget = null;
@@ -782,6 +805,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {
                throw new UnsupportedOperationException("VectorDrawableAnimator cannot be " +
                        "re-initialized");
            }
            mShouldIgnoreInvalidAnim = shouldIgnoreInvalidAnimation();
            parseAnimatorSet(set, 0);
            mInitialized = true;

@@ -841,7 +865,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {
                    }  else if (target instanceof VectorDrawable.VFullPath) {
                        createRTAnimatorForFullPath(animator, (VectorDrawable.VFullPath) target,
                                startTime);
                    } else {
                    } else if (!mShouldIgnoreInvalidAnim) {
                        throw new IllegalArgumentException("ClipPath only supports PathData " +
                                "property");
                    }
@@ -850,10 +874,11 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {
            } else if (target instanceof VectorDrawable.VectorDrawableState) {
                createRTAnimatorForRootGroup(values, animator,
                        (VectorDrawable.VectorDrawableState) target, startTime);
            } else {
            } else if (!mShouldIgnoreInvalidAnim) {
                // Should never get here
                throw new UnsupportedOperationException("Target should be either VGroup, VPath, " +
                        "or ConstantState, " + target.getClass() + " is not supported");
                        "or ConstantState, " + target == null ? "Null target" : target.getClass() +
                        " is not supported");
            }
        }

@@ -912,8 +937,12 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {
            long nativePtr = target.getNativePtr();
            if (mTmpValues.type == Float.class || mTmpValues.type == float.class) {
                if (propertyId < 0) {
                    throw new IllegalArgumentException("Property: " + mTmpValues
                            .propertyName + " is not supported for FullPath");
                    if (mShouldIgnoreInvalidAnim) {
                        return;
                    } else {
                        throw new IllegalArgumentException("Property: " + mTmpValues.propertyName
                                + " is not supported for FullPath");
                    }
                }
                propertyPtr = nCreatePathPropertyHolder(nativePtr, propertyId,
                        (Float) mTmpValues.startValue, (Float) mTmpValues.endValue);
@@ -921,11 +950,15 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {
            } else if (mTmpValues.type == Integer.class || mTmpValues.type == int.class) {
                propertyPtr = nCreatePathColorPropertyHolder(nativePtr, propertyId,
                        (Integer) mTmpValues.startValue, (Integer) mTmpValues.endValue);
            } else {
                if (mShouldIgnoreInvalidAnim) {
                    return;
                } else {
                    throw new UnsupportedOperationException("Unsupported type: " +
                            mTmpValues.type + ". Only float, int or PathData value is " +
                            "supported for Paths.");
                }
            }
            if (mTmpValues.dataSource != null) {
                float[] dataPoints = createDataPoints(mTmpValues.dataSource, animator
                        .getDuration());
@@ -939,8 +972,12 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {
                long startTime) {
                long nativePtr = target.getNativeRenderer();
                if (!animator.getPropertyName().equals("alpha")) {
                    throw new UnsupportedOperationException("Only alpha is supported for root " +
                            "group");
                    if (mShouldIgnoreInvalidAnim) {
                        return;
                    } else {
                        throw new UnsupportedOperationException("Only alpha is supported for root "
                                + "group");
                    }
                }
                Float startValue = null;
                Float endValue = null;
@@ -953,8 +990,12 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {
                    }
                }
                if (startValue == null && endValue == null) {
                    if (mShouldIgnoreInvalidAnim) {
                        return;
                    } else {
                        throw new UnsupportedOperationException("No alpha values are specified");
                    }
                }
                long propertyPtr = nCreateRootAlphaPropertyHolder(nativePtr, startValue, endValue);
                createNativeChildAnimator(propertyPtr, startTime, animator);
        }
+8 −34
Original line number Diff line number Diff line
@@ -924,8 +924,11 @@ public class VectorDrawable extends Drawable {
        private int mChangingConfigurations;
        private int[] mThemeAttrs;
        private String mGroupName = null;
        private long mNativePtr = 0;

        // The native object will be created in the constructor and will be destroyed in native
        // when the neither java nor native has ref to the tree. This pointer should be valid
        // throughout this VGroup Java object's life.
        private final long mNativePtr;
        public VGroup(VGroup copy, ArrayMap<String, Object> targetsMap) {

            mIsStateful = copy.mIsStateful;
@@ -1064,16 +1067,6 @@ public class VectorDrawable extends Drawable {
            return false;
        }

        @Override
        protected void finalize() throws Throwable {
            if (mNativePtr != 0) {
                nDestroy(mNativePtr);
                mNativePtr = 0;
            }
            super.finalize();
        }


        @Override
        public void applyTheme(Theme t) {
            if (mThemeAttrs != null) {
@@ -1208,10 +1201,10 @@ public class VectorDrawable extends Drawable {
     * Clip path, which only has name and pathData.
     */
    private static class VClipPath extends VPath {
        long mNativePtr = 0;
        private final long mNativePtr;

        public VClipPath() {
            mNativePtr = nCreateClipPath();
            // Empty constructor.
        }

        public VClipPath(VClipPath copy) {
@@ -1224,14 +1217,6 @@ public class VectorDrawable extends Drawable {
            return mNativePtr;
        }

        @Override
        protected void finalize() throws Throwable {
            if (mNativePtr != 0) {
                nDestroy(mNativePtr);
                mNativePtr = 0;
            }
            super.finalize();
        }
        @Override
        public void inflate(Resources r, AttributeSet attrs, Theme theme) {
            final TypedArray a = obtainAttributes(r, theme, attrs,
@@ -1317,10 +1302,9 @@ public class VectorDrawable extends Drawable {

        ComplexColor mStrokeColors = null;
        ComplexColor mFillColors = null;
        private long mNativePtr = 0;
        private final long mNativePtr;

        public VFullPath() {
            // Empty constructor.
            mNativePtr = nCreateFullPath();
        }

@@ -1384,15 +1368,6 @@ public class VectorDrawable extends Drawable {
            a.recycle();
        }

        @Override
        protected void finalize() throws Throwable {
            if (mNativePtr != 0) {
                nDestroy(mNativePtr);
                mNativePtr = 0;
            }
            super.finalize();
        }

        private void updateStateFromTypedArray(TypedArray a) {
            int byteCount = TOTAL_PROPERTY_COUNT * 4;
            if (mPropertyData == null) {
@@ -1647,7 +1622,7 @@ public class VectorDrawable extends Drawable {
    private static native void nDraw(long rendererPtr, long canvasWrapperPtr,
            long colorFilterPtr, Rect bounds, boolean needsMirroring, boolean canReuseCache);
    private static native long nCreateFullPath();
    private static native long nCreateFullPath(long mNativeFullPathPtr);
    private static native long nCreateFullPath(long nativeFullPathPtr);
    private static native boolean nGetFullPathProperties(long pathPtr, byte[] properties,
            int length);

@@ -1663,7 +1638,6 @@ public class VectorDrawable extends Drawable {

    private static native long nCreateGroup();
    private static native long nCreateGroup(long groupPtr);
    private static native void nDestroy(long nodePtr);
    private static native void nSetName(long nodePtr, String name);
    private static native boolean nGetGroupProperties(long groupPtr, float[] properties,
            int length);
+2 −2
Original line number Diff line number Diff line
@@ -324,7 +324,7 @@ void Group::draw(SkCanvas* outCanvas, const SkMatrix& currentMatrix, float scale
    // Save the current clip information, which is local to this group.
    outCanvas->save();
    // Draw the group tree in the same order as the XML file.
    for (Node* child : mChildren) {
    for (auto& child : mChildren) {
        child->draw(outCanvas, stackedMatrix, scaleX, scaleY);
    }
    // Restore the previous clip information.
@@ -361,7 +361,7 @@ void Group::getLocalMatrix(SkMatrix* outMatrix) {
}

void Group::addChild(Node* child) {
    mChildren.push_back(child);
    mChildren.emplace_back(child);
}

bool Group::getProperties(float* outProperties, int length) {
+2 −2
Original line number Diff line number Diff line
@@ -316,7 +316,7 @@ private:
        // Count of the properties, must be at the end.
        Count,
    };
    std::vector<Node*> mChildren;
    std::vector< std::unique_ptr<Node> > mChildren;
    Properties mProperties;
};

@@ -360,7 +360,7 @@ private:
    float mViewportHeight = 0;
    float mRootAlpha = 1.0f;

    Group* mRootNode;
    std::unique_ptr<Group> mRootNode;
    SkRect mBounds;
    SkMatrix mCanvasMatrix;
    SkPaint mPaint;