Merge "Check whether VD tree is still valid before calling native setter" into nyc-dev

This commit is contained in:
Doris Liu
2016-04-12 19:50:38 +00:00
committed by Android (Google) Code Review
2 changed files with 108 additions and 57 deletions

View File

@@ -343,7 +343,7 @@ static void setTrimPathOffset(JNIEnv*, jobject, jlong fullPathPtr, jfloat trimPa
}
static const JNINativeMethod gMethods[] = {
{"nCreateRenderer", "!(J)J", (void*)createTree},
{"nCreateTree", "!(J)J", (void*)createTree},
{"nSetRendererViewportSize", "!(JFF)V", (void*)setTreeViewportSize},
{"nSetRootAlpha", "!(JF)Z", (void*)setRootAlpha},
{"nGetRootAlpha", "!(J)F", (void*)getRootAlpha},

View File

@@ -534,13 +534,17 @@ public class VectorDrawable extends Drawable {
public void inflate(@NonNull Resources r, @NonNull XmlPullParser parser,
@NonNull AttributeSet attrs, @Nullable Theme theme)
throws XmlPullParserException, IOException {
if (mVectorState.mRootGroup != null || mVectorState.mNativeRendererRefBase != null) {
if (mVectorState.mRootGroup != null || mVectorState.mNativeTree != null) {
// This VD has been used to display other VD resource content, clean up.
mVectorState.mRootGroup = new VGroup();
if (mVectorState.mNativeRendererRefBase != null) {
mVectorState.mNativeRendererRefBase.release();
if (mVectorState.mRootGroup != null) {
// Remove child nodes' reference to tree
mVectorState.mRootGroup.setTree(null);
}
mVectorState.createNativeRenderer(mVectorState.mRootGroup.mNativePtr);
mVectorState.mRootGroup = new VGroup();
if (mVectorState.mNativeTree != null) {
mVectorState.mNativeTree.release();
}
mVectorState.createNativeTree(mVectorState.mRootGroup);
}
final VectorDrawableState state = mVectorState;
state.setDensity(Drawable.resolveDensity(r, 0));
@@ -734,7 +738,7 @@ public class VectorDrawable extends Drawable {
Insets mOpticalInsets = Insets.NONE;
String mRootName = null;
VGroup mRootGroup;
VirtualRefBasePtr mNativeRendererRefBase = null;
VirtualRefBasePtr mNativeTree = null;
int mDensity = DisplayMetrics.DENSITY_DEFAULT;
final ArrayMap<String, Object> mVGTargetsMap = new ArrayMap<>();
@@ -755,7 +759,7 @@ public class VectorDrawable extends Drawable {
mTintMode = copy.mTintMode;
mAutoMirrored = copy.mAutoMirrored;
mRootGroup = new VGroup(copy.mRootGroup, mVGTargetsMap);
createNativeRenderer(mRootGroup.mNativePtr);
createNativeTree(mRootGroup);
mBaseWidth = copy.mBaseWidth;
mBaseHeight = copy.mBaseHeight;
@@ -770,15 +774,16 @@ public class VectorDrawable extends Drawable {
}
}
private void createNativeRenderer(long rootGroupPtr) {
mNativeRendererRefBase = new VirtualRefBasePtr(nCreateRenderer(rootGroupPtr));
private void createNativeTree(VGroup rootGroup) {
mNativeTree = new VirtualRefBasePtr(nCreateTree(rootGroup.mNativePtr));
mRootGroup.setTree(mNativeTree);
}
long getNativeRenderer() {
if (mNativeRendererRefBase == null) {
if (mNativeTree == null) {
return 0;
}
return mNativeRendererRefBase.get();
return mNativeTree.get();
}
public boolean canReuseCache() {
@@ -817,7 +822,7 @@ public class VectorDrawable extends Drawable {
public VectorDrawableState() {
mRootGroup = new VGroup();
createNativeRenderer(mRootGroup.mNativePtr);
createNativeTree(mRootGroup);
}
@Override
@@ -881,16 +886,16 @@ public class VectorDrawable extends Drawable {
* has changed.
*/
public boolean setAlpha(float alpha) {
return nSetRootAlpha(mNativeRendererRefBase.get(), alpha);
return nSetRootAlpha(mNativeTree.get(), alpha);
}
@SuppressWarnings("unused")
public float getAlpha() {
return nGetRootAlpha(mNativeRendererRefBase.get());
return nGetRootAlpha(mNativeTree.get());
}
}
static class VGroup implements VObject {
static class VGroup extends VObject {
private static final int ROTATE_INDEX = 0;
private static final int PIVOT_X_INDEX = 1;
private static final int PIVOT_Y_INDEX = 2;
@@ -984,10 +989,17 @@ public class VectorDrawable extends Drawable {
public void addChild(VObject child) {
nAddChild(mNativePtr, child.getNativePtr());
mChildren.add(child);
mIsStateful |= child.isStateful();
}
@Override
public void setTree(VirtualRefBasePtr treeRoot) {
super.setTree(treeRoot);
for (int i = 0; i < mChildren.size(); i++) {
mChildren.get(i).setTree(treeRoot);
}
}
@Override
public long getNativePtr() {
return mNativePtr;
@@ -1101,79 +1113,93 @@ public class VectorDrawable extends Drawable {
/* Setters and Getters, used by animator from AnimatedVectorDrawable. */
@SuppressWarnings("unused")
public float getRotation() {
return nGetRotation(mNativePtr);
return isTreeValid() ? nGetRotation(mNativePtr) : 0;
}
@SuppressWarnings("unused")
public void setRotation(float rotation) {
nSetRotation(mNativePtr, rotation);
if (isTreeValid()) {
nSetRotation(mNativePtr, rotation);
}
}
@SuppressWarnings("unused")
public float getPivotX() {
return nGetPivotX(mNativePtr);
return isTreeValid() ? nGetPivotX(mNativePtr) : 0;
}
@SuppressWarnings("unused")
public void setPivotX(float pivotX) {
nSetPivotX(mNativePtr, pivotX);
if (isTreeValid()) {
nSetPivotX(mNativePtr, pivotX);
}
}
@SuppressWarnings("unused")
public float getPivotY() {
return nGetPivotY(mNativePtr);
return isTreeValid() ? nGetPivotY(mNativePtr) : 0;
}
@SuppressWarnings("unused")
public void setPivotY(float pivotY) {
nSetPivotY(mNativePtr, pivotY);
if (isTreeValid()) {
nSetPivotY(mNativePtr, pivotY);
}
}
@SuppressWarnings("unused")
public float getScaleX() {
return nGetScaleX(mNativePtr);
return isTreeValid() ? nGetScaleX(mNativePtr) : 0;
}
@SuppressWarnings("unused")
public void setScaleX(float scaleX) {
nSetScaleX(mNativePtr, scaleX);
if (isTreeValid()) {
nSetScaleX(mNativePtr, scaleX);
}
}
@SuppressWarnings("unused")
public float getScaleY() {
return nGetScaleY(mNativePtr);
return isTreeValid() ? nGetScaleY(mNativePtr) : 0;
}
@SuppressWarnings("unused")
public void setScaleY(float scaleY) {
nSetScaleY(mNativePtr, scaleY);
if (isTreeValid()) {
nSetScaleY(mNativePtr, scaleY);
}
}
@SuppressWarnings("unused")
public float getTranslateX() {
return nGetTranslateX(mNativePtr);
return isTreeValid() ? nGetTranslateX(mNativePtr) : 0;
}
@SuppressWarnings("unused")
public void setTranslateX(float translateX) {
nSetTranslateX(mNativePtr, translateX);
if (isTreeValid()) {
nSetTranslateX(mNativePtr, translateX);
}
}
@SuppressWarnings("unused")
public float getTranslateY() {
return nGetTranslateY(mNativePtr);
return isTreeValid() ? nGetTranslateY(mNativePtr) : 0;
}
@SuppressWarnings("unused")
public void setTranslateY(float translateY) {
nSetTranslateY(mNativePtr, translateY);
if (isTreeValid()) {
nSetTranslateY(mNativePtr, translateY);
}
}
}
/**
* Common Path information for clip path and normal path.
*/
static abstract class VPath implements VObject {
static abstract class VPath extends VObject {
protected PathParser.PathData mPathData = null;
String mPathName;
@@ -1203,7 +1229,9 @@ public class VectorDrawable extends Drawable {
@SuppressWarnings("unused")
public void setPathData(PathParser.PathData pathData) {
mPathData.setPathData(pathData);
nSetPathData(getNativePtr(), mPathData.getNativePtr());
if (isTreeValid()) {
nSetPathData(getNativePtr(), mPathData.getNativePtr());
}
}
}
@@ -1549,97 +1577,120 @@ public class VectorDrawable extends Drawable {
/* Setters and Getters, used by animator from AnimatedVectorDrawable. */
@SuppressWarnings("unused")
int getStrokeColor() {
return nGetStrokeColor(mNativePtr);
return isTreeValid() ? nGetStrokeColor(mNativePtr) : 0;
}
@SuppressWarnings("unused")
void setStrokeColor(int strokeColor) {
mStrokeColors = null;
nSetStrokeColor(mNativePtr, strokeColor);
if (isTreeValid()) {
nSetStrokeColor(mNativePtr, strokeColor);
}
}
@SuppressWarnings("unused")
float getStrokeWidth() {
return nGetStrokeWidth(mNativePtr);
return isTreeValid() ? nGetStrokeWidth(mNativePtr) : 0;
}
@SuppressWarnings("unused")
void setStrokeWidth(float strokeWidth) {
nSetStrokeWidth(mNativePtr, strokeWidth);
if (isTreeValid()) {
nSetStrokeWidth(mNativePtr, strokeWidth);
}
}
@SuppressWarnings("unused")
float getStrokeAlpha() {
return nGetStrokeAlpha(mNativePtr);
return isTreeValid() ? nGetStrokeAlpha(mNativePtr) : 0;
}
@SuppressWarnings("unused")
void setStrokeAlpha(float strokeAlpha) {
nSetStrokeAlpha(mNativePtr, strokeAlpha);
if (isTreeValid()) {
nSetStrokeAlpha(mNativePtr, strokeAlpha);
}
}
@SuppressWarnings("unused")
int getFillColor() {
return nGetFillColor(mNativePtr);
return isTreeValid() ? nGetFillColor(mNativePtr) : 0;
}
@SuppressWarnings("unused")
void setFillColor(int fillColor) {
mFillColors = null;
nSetFillColor(mNativePtr, fillColor);
if (isTreeValid()) {
nSetFillColor(mNativePtr, fillColor);
}
}
@SuppressWarnings("unused")
float getFillAlpha() {
return nGetFillAlpha(mNativePtr);
return isTreeValid() ? nGetFillAlpha(mNativePtr) : 0;
}
@SuppressWarnings("unused")
void setFillAlpha(float fillAlpha) {
nSetFillAlpha(mNativePtr, fillAlpha);
if (isTreeValid()) {
nSetFillAlpha(mNativePtr, fillAlpha);
}
}
@SuppressWarnings("unused")
float getTrimPathStart() {
return nGetTrimPathStart(mNativePtr);
return isTreeValid() ? nGetTrimPathStart(mNativePtr) : 0;
}
@SuppressWarnings("unused")
void setTrimPathStart(float trimPathStart) {
nSetTrimPathStart(mNativePtr, trimPathStart);
if (isTreeValid()) {
nSetTrimPathStart(mNativePtr, trimPathStart);
}
}
@SuppressWarnings("unused")
float getTrimPathEnd() {
return nGetTrimPathEnd(mNativePtr);
return isTreeValid() ? nGetTrimPathEnd(mNativePtr) : 0;
}
@SuppressWarnings("unused")
void setTrimPathEnd(float trimPathEnd) {
nSetTrimPathEnd(mNativePtr, trimPathEnd);
if (isTreeValid()) {
nSetTrimPathEnd(mNativePtr, trimPathEnd);
}
}
@SuppressWarnings("unused")
float getTrimPathOffset() {
return nGetTrimPathOffset(mNativePtr);
return isTreeValid() ? nGetTrimPathOffset(mNativePtr) : 0;
}
@SuppressWarnings("unused")
void setTrimPathOffset(float trimPathOffset) {
nSetTrimPathOffset(mNativePtr, trimPathOffset);
if (isTreeValid()) {
nSetTrimPathOffset(mNativePtr, trimPathOffset);
}
}
}
interface VObject {
long getNativePtr();
void inflate(Resources r, AttributeSet attrs, Theme theme);
boolean canApplyTheme();
void applyTheme(Theme t);
boolean onStateChange(int[] state);
boolean isStateful();
abstract static class VObject {
VirtualRefBasePtr mTreePtr = null;
boolean isTreeValid() {
return mTreePtr != null && mTreePtr.get() != 0;
}
void setTree(VirtualRefBasePtr ptr) {
mTreePtr = ptr;
}
abstract long getNativePtr();
abstract void inflate(Resources r, AttributeSet attrs, Theme theme);
abstract boolean canApplyTheme();
abstract void applyTheme(Theme t);
abstract boolean onStateChange(int[] state);
abstract boolean isStateful();
}
private static native long nCreateRenderer(long rootGroupPtr);
private static native long nCreateTree(long rootGroupPtr);
private static native void nSetRendererViewportSize(long rendererPtr, float viewportWidth,
float viewportHeight);
private static native boolean nSetRootAlpha(long rendererPtr, float alpha);