Merge "Change BridgeResources to Resources_Delegate" into nyc-dev
diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
index 697dfbf..d0e431a 100644
--- a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
@@ -65,7 +65,7 @@
*/
public final class BridgeTypedArray extends TypedArray {
- private final BridgeResources mBridgeResources;
+ private final Resources mBridgeResources;
private final BridgeContext mContext;
private final boolean mPlatformFile;
@@ -78,7 +78,7 @@
@Nullable
private int[] mEmptyIds;
- public BridgeTypedArray(BridgeResources resources, BridgeContext context, int len,
+ public BridgeTypedArray(Resources resources, BridgeContext context, int len,
boolean platformFile) {
super(resources, null, null, 0);
mBridgeResources = resources;
@@ -701,7 +701,8 @@
if (resVal instanceof ArrayResourceValue) {
ArrayResourceValue array = (ArrayResourceValue) resVal;
int count = array.getElementCount();
- return count >= 0 ? mBridgeResources.fillValues(array, new CharSequence[count]) : null;
+ return count >= 0 ? Resources_Delegate.fillValues(mBridgeResources, array, new CharSequence[count]) :
+ null;
}
int id = getResourceId(index, 0);
String resIdMessage = id > 0 ? " (resource id 0x" + Integer.toHexString(id) + ')' : "";
@@ -949,7 +950,6 @@
}
static TypedArray obtain(Resources res, int len) {
- return res instanceof BridgeResources ?
- new BridgeTypedArray(((BridgeResources) res), null, len, true) : null;
+ return new BridgeTypedArray(res, null, len, true);
}
}
diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java b/tools/layoutlib/bridge/src/android/content/res/Resources_Delegate.java
similarity index 63%
rename from tools/layoutlib/bridge/src/android/content/res/BridgeResources.java
rename to tools/layoutlib/bridge/src/android/content/res/Resources_Delegate.java
index fe46480..985dd5a 100644
--- a/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java
+++ b/tools/layoutlib/bridge/src/android/content/res/Resources_Delegate.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,8 +28,10 @@
import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
import com.android.layoutlib.bridge.impl.ParserFactory;
import com.android.layoutlib.bridge.impl.ResourceHelper;
+import com.android.layoutlib.bridge.util.NinePatchInputStream;
import com.android.ninepatch.NinePatch;
import com.android.resources.ResourceType;
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import com.android.util.Pair;
import org.xmlpull.v1.XmlPullParser;
@@ -37,6 +39,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.content.res.Resources.NotFoundException;
+import android.content.res.Resources.Theme;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
@@ -50,132 +54,101 @@
import java.util.Iterator;
@SuppressWarnings("deprecation")
-public final class BridgeResources extends Resources {
+public class Resources_Delegate {
- private BridgeContext mContext;
- private LayoutlibCallback mLayoutlibCallback;
- private boolean[] mPlatformResourceFlag = new boolean[1];
- private TypedValue mTmpValue = new TypedValue();
+ private static boolean[] mPlatformResourceFlag = new boolean[1];
- /**
- * Simpler wrapper around FileInputStream. This is used when the input stream represent
- * not a normal bitmap but a nine patch.
- * This is useful when the InputStream is created in a method but used in another that needs
- * to know whether this is 9-patch or not, such as BitmapFactory.
- */
- public class NinePatchInputStream extends FileInputStream {
- private boolean mFakeMarkSupport = true;
- public NinePatchInputStream(File file) throws FileNotFoundException {
- super(file);
- }
-
- @Override
- public boolean markSupported() {
- //noinspection SimplifiableIfStatement
- if (mFakeMarkSupport) {
- // this is needed so that BitmapFactory doesn't wrap this in a BufferedInputStream.
- return true;
- }
-
- return super.markSupported();
- }
-
- public void disableFakeMarkSupport() {
- // disable fake mark support so that in case codec actually try to use them
- // we don't lie to them.
- mFakeMarkSupport = false;
- }
- }
-
- /**
- * This initializes the static field {@link Resources#mSystem} which is used
- * by methods who get global resources using {@link Resources#getSystem()}.
- * <p/>
- * They will end up using our bridge resources.
- * <p/>
- * {@link Bridge} calls this method after setting up a new bridge.
- */
public static Resources initSystem(BridgeContext context,
AssetManager assets,
DisplayMetrics metrics,
Configuration config,
LayoutlibCallback layoutlibCallback) {
- return Resources.mSystem = new BridgeResources(context,
- assets,
- metrics,
- config,
- layoutlibCallback);
+ Resources resources = new Resources(assets, metrics, config);
+ resources.mContext = context;
+ resources.mLayoutlibCallback = layoutlibCallback;
+ return Resources.mSystem = resources;
}
/**
- * Disposes the static {@link Resources#mSystem} to make sure we don't leave objects
- * around that would prevent us from unloading the library.
+ * Disposes the static {@link Resources#mSystem} to make sure we don't leave objects around that
+ * would prevent us from unloading the library.
*/
public static void disposeSystem() {
- if (Resources.mSystem instanceof BridgeResources) {
- ((BridgeResources)(Resources.mSystem)).mContext = null;
- ((BridgeResources)(Resources.mSystem)).mLayoutlibCallback = null;
- }
+ Resources.mSystem.mContext = null;
+ Resources.mSystem.mLayoutlibCallback = null;
Resources.mSystem = null;
}
- private BridgeResources(BridgeContext context, AssetManager assets, DisplayMetrics metrics,
- Configuration config, LayoutlibCallback layoutlibCallback) {
- super(assets, metrics, config);
- mContext = context;
- mLayoutlibCallback = layoutlibCallback;
+ public static BridgeTypedArray newTypeArray(Resources resources, int numEntries,
+ boolean platformFile) {
+ return new BridgeTypedArray(resources, resources.mContext, numEntries, platformFile);
}
- public BridgeTypedArray newTypeArray(int numEntries, boolean platformFile) {
- return new BridgeTypedArray(this, mContext, numEntries, platformFile);
- }
-
- private Pair<String, ResourceValue> getResourceValue(int id, boolean[] platformResFlag_out) {
+ private static Pair<String, ResourceValue> getResourceValue(Resources resources, int id,
+ boolean[] platformResFlag_out) {
// first get the String related to this id in the framework
Pair<ResourceType, String> resourceInfo = Bridge.resolveResourceId(id);
+ // Set the layoutlib callback and context for resources
+ if (resources != Resources.mSystem && resources.mLayoutlibCallback == null) {
+ resources.mLayoutlibCallback = Resources.mSystem.mLayoutlibCallback;
+ resources.mContext = Resources.mSystem.mContext;
+ }
+
if (resourceInfo != null) {
platformResFlag_out[0] = true;
String attributeName = resourceInfo.getSecond();
- return Pair.of(attributeName, mContext.getRenderResources().getFrameworkResource(
- resourceInfo.getFirst(), attributeName));
+ return Pair.of(attributeName,
+ resources.mContext.getRenderResources().getFrameworkResource(
+ resourceInfo.getFirst(), attributeName));
}
// didn't find a match in the framework? look in the project.
- if (mLayoutlibCallback != null) {
- resourceInfo = mLayoutlibCallback.resolveResourceId(id);
+ if (resources.mLayoutlibCallback != null) {
+ resourceInfo = resources.mLayoutlibCallback.resolveResourceId(id);
if (resourceInfo != null) {
platformResFlag_out[0] = false;
String attributeName = resourceInfo.getSecond();
- return Pair.of(attributeName, mContext.getRenderResources().getProjectResource(
- resourceInfo.getFirst(), attributeName));
+ return Pair.of(attributeName,
+ resources.mContext.getRenderResources().getProjectResource(
+ resourceInfo.getFirst(), attributeName));
}
}
return null;
}
- @Override
- public Drawable getDrawable(int id, Theme theme) {
- Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
+ @LayoutlibDelegate
+ static Drawable getDrawable(Resources resources, int id) {
+ return getDrawable(resources, id, null);
+ }
+
+ @LayoutlibDelegate
+ static Drawable getDrawable(Resources resources, int id, Theme theme) {
+ Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);
if (value != null) {
- return ResourceHelper.getDrawable(value.getSecond(), mContext, theme);
+ return ResourceHelper.getDrawable(value.getSecond(), resources.mContext, theme);
}
// id was not found or not resolved. Throw a NotFoundException.
- throwException(id);
+ throwException(resources, id);
// this is not used since the method above always throws
return null;
}
- @Override
- public int getColor(int id, Theme theme) throws NotFoundException {
- Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
+ @LayoutlibDelegate
+ static int getColor(Resources resources, int id) {
+ return getColor(resources, id, null);
+ }
+
+ @LayoutlibDelegate
+ static int getColor(Resources resources, int id, Theme theme) throws NotFoundException {
+ Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);
if (value != null) {
ResourceValue resourceValue = value.getSecond();
@@ -187,7 +160,7 @@
String message;
if (new File(resourceValue.getValue()).isFile()) {
String resource = (resourceValue.isFramework() ? "@android:" : "@") + "color/"
- + resourceValue.getName();
+ + resourceValue.getName();
message = "Hexadecimal color expected, found Color State List for " + resource;
} else {
message = e.getMessage();
@@ -200,31 +173,57 @@
// Suppress possible NPE. getColorStateList will never return null, it will instead
// throw an exception, but intelliJ can't figure that out
//noinspection ConstantConditions
- return getColorStateList(id, theme).getDefaultColor();
+ return getColorStateList(resources, id, theme).getDefaultColor();
}
- @Override
- public ColorStateList getColorStateList(int id, Theme theme) throws NotFoundException {
- Pair<String, ResourceValue> resValue = getResourceValue(id, mPlatformResourceFlag);
+ @LayoutlibDelegate
+ static ColorStateList getColorStateList(Resources resources, int id) throws NotFoundException {
+ return getColorStateList(resources, id, null);
+ }
+
+ @LayoutlibDelegate
+ static ColorStateList getColorStateList(Resources resources, int id, Theme theme)
+ throws NotFoundException {
+ Pair<String, ResourceValue> resValue =
+ getResourceValue(resources, id, mPlatformResourceFlag);
if (resValue != null) {
ColorStateList stateList = ResourceHelper.getColorStateList(resValue.getSecond(),
- mContext);
+ resources.mContext);
if (stateList != null) {
return stateList.obtainForTheme(theme);
}
}
// id was not found or not resolved. Throw a NotFoundException.
- throwException(id);
+ throwException(resources, id);
// this is not used since the method above always throws
return null;
}
- @Override
- public CharSequence getText(int id) throws NotFoundException {
- Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
+ @LayoutlibDelegate
+ static CharSequence getText(Resources resources, int id, CharSequence def) {
+ Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);
+
+ if (value != null) {
+ ResourceValue resValue = value.getSecond();
+
+ assert resValue != null;
+ if (resValue != null) {
+ String v = resValue.getValue();
+ if (v != null) {
+ return v;
+ }
+ }
+ }
+
+ return def;
+ }
+
+ @LayoutlibDelegate
+ static CharSequence getText(Resources resources, int id) throws NotFoundException {
+ Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);
if (value != null) {
ResourceValue resValue = value.getSecond();
@@ -239,38 +238,38 @@
}
// id was not found or not resolved. Throw a NotFoundException.
- throwException(id);
+ throwException(resources, id);
// this is not used since the method above always throws
return null;
}
- @Override
- public CharSequence[] getTextArray(int id) throws NotFoundException {
- ResourceValue resValue = getArrayResourceValue(id);
+ @LayoutlibDelegate
+ static CharSequence[] getTextArray(Resources resources, int id) throws NotFoundException {
+ ResourceValue resValue = getArrayResourceValue(resources, id);
if (resValue == null) {
// Error already logged by getArrayResourceValue.
return new CharSequence[0];
} else if (!(resValue instanceof ArrayResourceValue)) {
return new CharSequence[]{
- resolveReference(resValue.getValue(), resValue.isFramework())};
+ resolveReference(resources, resValue.getValue(), resValue.isFramework())};
}
ArrayResourceValue arv = ((ArrayResourceValue) resValue);
- return fillValues(arv, new CharSequence[arv.getElementCount()]);
+ return fillValues(resources, arv, new CharSequence[arv.getElementCount()]);
}
- @Override
- public String[] getStringArray(int id) throws NotFoundException {
- ResourceValue resValue = getArrayResourceValue(id);
+ @LayoutlibDelegate
+ static String[] getStringArray(Resources resources, int id) throws NotFoundException {
+ ResourceValue resValue = getArrayResourceValue(resources, id);
if (resValue == null) {
// Error already logged by getArrayResourceValue.
return new String[0];
} else if (!(resValue instanceof ArrayResourceValue)) {
return new String[]{
- resolveReference(resValue.getValue(), resValue.isFramework())};
+ resolveReference(resources, resValue.getValue(), resValue.isFramework())};
}
ArrayResourceValue arv = ((ArrayResourceValue) resValue);
- return fillValues(arv, new String[arv.getElementCount()]);
+ return fillValues(resources, arv, new String[arv.getElementCount()]);
}
/**
@@ -278,25 +277,26 @@
* always Strings. The ideal signature for the method should be <T super String>, but java
* generics don't support it.
*/
- <T extends CharSequence> T[] fillValues(ArrayResourceValue resValue, T[] values) {
+ static <T extends CharSequence> T[] fillValues(Resources resources, ArrayResourceValue resValue,
+ T[] values) {
int i = 0;
for (Iterator<String> iterator = resValue.iterator(); iterator.hasNext(); i++) {
@SuppressWarnings("unchecked")
- T s = (T) resolveReference(iterator.next(), resValue.isFramework());
+ T s = (T) resolveReference(resources, iterator.next(), resValue.isFramework());
values[i] = s;
}
return values;
}
- @Override
- public int[] getIntArray(int id) throws NotFoundException {
- ResourceValue rv = getArrayResourceValue(id);
+ @LayoutlibDelegate
+ static int[] getIntArray(Resources resources, int id) throws NotFoundException {
+ ResourceValue rv = getArrayResourceValue(resources, id);
if (rv == null) {
// Error already logged by getArrayResourceValue.
return new int[0];
} else if (!(rv instanceof ArrayResourceValue)) {
// This is an older IDE that can only give us the first element of the array.
- String firstValue = resolveReference(rv.getValue(), rv.isFramework());
+ String firstValue = resolveReference(resources, rv.getValue(), rv.isFramework());
try {
return new int[]{getInt(firstValue)};
} catch (NumberFormatException e) {
@@ -310,7 +310,7 @@
int[] values = new int[resValue.getElementCount()];
int i = 0;
for (Iterator<String> iterator = resValue.iterator(); iterator.hasNext(); i++) {
- String element = resolveReference(iterator.next(), resValue.isFramework());
+ String element = resolveReference(resources, iterator.next(), resValue.isFramework());
try {
values[i] = getInt(element);
} catch (NumberFormatException e) {
@@ -330,11 +330,13 @@
* method returns the ResourceValue. This happens on older versions of the IDE, which did not
* parse the array resources properly.
* <p/>
+ *
* @throws NotFoundException if no resource if found
*/
@Nullable
- private ResourceValue getArrayResourceValue(int id) throws NotFoundException {
- Pair<String, ResourceValue> v = getResourceValue(id, mPlatformResourceFlag);
+ private static ResourceValue getArrayResourceValue(Resources resources, int id)
+ throws NotFoundException {
+ Pair<String, ResourceValue> v = getResourceValue(resources, id, mPlatformResourceFlag);
if (v != null) {
ResourceValue resValue = v.getSecond();
@@ -360,19 +362,20 @@
}
// id was not found or not resolved. Throw a NotFoundException.
- throwException(id);
+ throwException(resources, id);
// this is not used since the method above always throws
return null;
}
@NonNull
- private String resolveReference(@NonNull String ref, boolean forceFrameworkOnly) {
+ private static String resolveReference(Resources resources, @NonNull String ref,
+ boolean forceFrameworkOnly) {
if (ref.startsWith(SdkConstants.PREFIX_RESOURCE_REF) || ref.startsWith
(SdkConstants.PREFIX_THEME_REF)) {
ResourceValue rv =
- mContext.getRenderResources().findResValue(ref, forceFrameworkOnly);
- rv = mContext.getRenderResources().resolveResValue(rv);
+ resources.mContext.getRenderResources().findResValue(ref, forceFrameworkOnly);
+ rv = resources.mContext.getRenderResources().resolveResValue(rv);
if (rv != null) {
return rv.getValue();
} else {
@@ -384,9 +387,9 @@
return ref;
}
- @Override
- public XmlResourceParser getLayout(int id) throws NotFoundException {
- Pair<String, ResourceValue> v = getResourceValue(id, mPlatformResourceFlag);
+ @LayoutlibDelegate
+ static XmlResourceParser getLayout(Resources resources, int id) throws NotFoundException {
+ Pair<String, ResourceValue> v = getResourceValue(resources, id, mPlatformResourceFlag);
if (v != null) {
ResourceValue value = v.getSecond();
@@ -394,8 +397,8 @@
try {
// check if the current parser can provide us with a custom parser.
- if (mPlatformResourceFlag[0] == false) {
- parser = mLayoutlibCallback.getParser(value);
+ if (!mPlatformResourceFlag[0]) {
+ parser = resources.mLayoutlibCallback.getParser(value);
}
// create a new one manually if needed.
@@ -409,7 +412,8 @@
}
if (parser != null) {
- return new BridgeXmlBlockParser(parser, mContext, mPlatformResourceFlag[0]);
+ return new BridgeXmlBlockParser(parser, resources.mContext,
+ mPlatformResourceFlag[0]);
}
} catch (XmlPullParserException e) {
Bridge.getLog().error(LayoutLog.TAG_BROKEN,
@@ -422,19 +426,19 @@
}
// id was not found or not resolved. Throw a NotFoundException.
- throwException(id);
+ throwException(resources, id);
// this is not used since the method above always throws
return null;
}
- @Override
- public XmlResourceParser getAnimation(int id) throws NotFoundException {
- Pair<String, ResourceValue> v = getResourceValue(id, mPlatformResourceFlag);
+ @LayoutlibDelegate
+ static XmlResourceParser getAnimation(Resources resources, int id) throws NotFoundException {
+ Pair<String, ResourceValue> v = getResourceValue(resources, id, mPlatformResourceFlag);
if (v != null) {
ResourceValue value = v.getSecond();
- XmlPullParser parser = null;
+ XmlPullParser parser;
try {
File xml = new File(value.getValue());
@@ -443,7 +447,8 @@
// give that to our XmlBlockParser
parser = ParserFactory.create(xml);
- return new BridgeXmlBlockParser(parser, mContext, mPlatformResourceFlag[0]);
+ return new BridgeXmlBlockParser(parser, resources.mContext,
+ mPlatformResourceFlag[0]);
}
} catch (XmlPullParserException e) {
Bridge.getLog().error(LayoutLog.TAG_BROKEN,
@@ -456,26 +461,31 @@
}
// id was not found or not resolved. Throw a NotFoundException.
- throwException(id);
+ throwException(resources, id);
// this is not used since the method above always throws
return null;
}
- @Override
- public TypedArray obtainAttributes(AttributeSet set, int[] attrs) {
- return mContext.obtainStyledAttributes(set, attrs);
+ @LayoutlibDelegate
+ static TypedArray obtainAttributes(Resources resources, AttributeSet set, int[] attrs) {
+ return resources.mContext.obtainStyledAttributes(set, attrs);
}
- @Override
- public TypedArray obtainTypedArray(int id) throws NotFoundException {
+ @LayoutlibDelegate
+ static TypedArray obtainAttributes(Resources resources, Resources.Theme theme, AttributeSet
+ set, int[] attrs) {
+ return Resources.obtainAttributes_Original(resources, theme, set, attrs);
+ }
+
+ @LayoutlibDelegate
+ static TypedArray obtainTypedArray(Resources resources, int id) throws NotFoundException {
throw new UnsupportedOperationException();
}
-
- @Override
- public float getDimension(int id) throws NotFoundException {
- Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
+ @LayoutlibDelegate
+ static float getDimension(Resources resources, int id) throws NotFoundException {
+ Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);
if (value != null) {
ResourceValue resValue = value.getSecond();
@@ -490,26 +500,26 @@
} else if (v.equals(BridgeConstants.WRAP_CONTENT)) {
return LayoutParams.WRAP_CONTENT;
}
-
+ TypedValue tmpValue = new TypedValue();
if (ResourceHelper.parseFloatAttribute(
- value.getFirst(), v, mTmpValue, true /*requireUnit*/) &&
- mTmpValue.type == TypedValue.TYPE_DIMENSION) {
- return mTmpValue.getDimension(getDisplayMetrics());
+ value.getFirst(), v, tmpValue, true /*requireUnit*/) &&
+ tmpValue.type == TypedValue.TYPE_DIMENSION) {
+ return tmpValue.getDimension(resources.getDisplayMetrics());
}
}
}
}
// id was not found or not resolved. Throw a NotFoundException.
- throwException(id);
+ throwException(resources, id);
// this is not used since the method above always throws
return 0;
}
- @Override
- public int getDimensionPixelOffset(int id) throws NotFoundException {
- Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
+ @LayoutlibDelegate
+ static int getDimensionPixelOffset(Resources resources, int id) throws NotFoundException {
+ Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);
if (value != null) {
ResourceValue resValue = value.getSecond();
@@ -518,26 +528,27 @@
if (resValue != null) {
String v = resValue.getValue();
if (v != null) {
+ TypedValue tmpValue = new TypedValue();
if (ResourceHelper.parseFloatAttribute(
- value.getFirst(), v, mTmpValue, true /*requireUnit*/) &&
- mTmpValue.type == TypedValue.TYPE_DIMENSION) {
- return TypedValue.complexToDimensionPixelOffset(mTmpValue.data,
- getDisplayMetrics());
+ value.getFirst(), v, tmpValue, true /*requireUnit*/) &&
+ tmpValue.type == TypedValue.TYPE_DIMENSION) {
+ return TypedValue.complexToDimensionPixelOffset(tmpValue.data,
+ resources.getDisplayMetrics());
}
}
}
}
// id was not found or not resolved. Throw a NotFoundException.
- throwException(id);
+ throwException(resources, id);
// this is not used since the method above always throws
return 0;
}
- @Override
- public int getDimensionPixelSize(int id) throws NotFoundException {
- Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
+ @LayoutlibDelegate
+ static int getDimensionPixelSize(Resources resources, int id) throws NotFoundException {
+ Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);
if (value != null) {
ResourceValue resValue = value.getSecond();
@@ -546,26 +557,27 @@
if (resValue != null) {
String v = resValue.getValue();
if (v != null) {
+ TypedValue tmpValue = new TypedValue();
if (ResourceHelper.parseFloatAttribute(
- value.getFirst(), v, mTmpValue, true /*requireUnit*/) &&
- mTmpValue.type == TypedValue.TYPE_DIMENSION) {
- return TypedValue.complexToDimensionPixelSize(mTmpValue.data,
- getDisplayMetrics());
+ value.getFirst(), v, tmpValue, true /*requireUnit*/) &&
+ tmpValue.type == TypedValue.TYPE_DIMENSION) {
+ return TypedValue.complexToDimensionPixelSize(tmpValue.data,
+ resources.getDisplayMetrics());
}
}
}
}
// id was not found or not resolved. Throw a NotFoundException.
- throwException(id);
+ throwException(resources, id);
// this is not used since the method above always throws
return 0;
}
- @Override
- public int getInteger(int id) throws NotFoundException {
- Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
+ @LayoutlibDelegate
+ static int getInteger(Resources resources, int id) throws NotFoundException {
+ Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);
if (value != null) {
ResourceValue resValue = value.getSecond();
@@ -584,15 +596,15 @@
}
// id was not found or not resolved. Throw a NotFoundException.
- throwException(id);
+ throwException(resources, id);
// this is not used since the method above always throws
return 0;
}
- @Override
- public boolean getBoolean(int id) throws NotFoundException {
- Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
+ @LayoutlibDelegate
+ static boolean getBoolean(Resources resources, int id) throws NotFoundException {
+ Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);
if (value != null) {
ResourceValue resValue = value.getSecond();
@@ -606,61 +618,62 @@
}
// id was not found or not resolved. Throw a NotFoundException.
- throwException(id);
+ throwException(resources, id);
// this is not used since the method above always throws
return false;
}
- @Override
- public String getResourceEntryName(int resid) throws NotFoundException {
+ @LayoutlibDelegate
+ static String getResourceEntryName(Resources resources, int resid) throws NotFoundException {
throw new UnsupportedOperationException();
}
- @Override
- public String getResourceName(int resid) throws NotFoundException {
+ @LayoutlibDelegate
+ static String getResourceName(Resources resources, int resid) throws NotFoundException {
throw new UnsupportedOperationException();
}
- @Override
- public String getResourceTypeName(int resid) throws NotFoundException {
+ @LayoutlibDelegate
+ static String getResourceTypeName(Resources resources, int resid) throws NotFoundException {
throw new UnsupportedOperationException();
}
- @Override
- public String getString(int id, Object... formatArgs) throws NotFoundException {
- String s = getString(id);
+ @LayoutlibDelegate
+ static String getString(Resources resources, int id, Object... formatArgs)
+ throws NotFoundException {
+ String s = getString(resources, id);
if (s != null) {
return String.format(s, formatArgs);
}
// id was not found or not resolved. Throw a NotFoundException.
- throwException(id);
+ throwException(resources, id);
// this is not used since the method above always throws
return null;
}
- @Override
- public String getString(int id) throws NotFoundException {
- Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
+ @LayoutlibDelegate
+ static String getString(Resources resources, int id) throws NotFoundException {
+ Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);
if (value != null && value.getSecond().getValue() != null) {
return value.getSecond().getValue();
}
// id was not found or not resolved. Throw a NotFoundException.
- throwException(id);
+ throwException(resources, id);
// this is not used since the method above always throws
return null;
}
- @Override
- public void getValue(int id, TypedValue outValue, boolean resolveRefs)
+ @LayoutlibDelegate
+ static void getValue(Resources resources, int id, TypedValue outValue, boolean resolveRefs)
throws NotFoundException {
- Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
+ Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);
if (value != null) {
ResourceValue resVal = value.getSecond();
@@ -673,7 +686,7 @@
}
if (resVal instanceof DensityBasedResourceValue) {
outValue.density =
- ((DensityBasedResourceValue) resVal).getResourceDensity().getDpiValue();
+ ((DensityBasedResourceValue) resVal).getResourceDensity().getDpiValue();
}
// else it's a string
@@ -684,18 +697,18 @@
}
// id was not found or not resolved. Throw a NotFoundException.
- throwException(id);
+ throwException(resources, id);
}
- @Override
- public void getValue(String name, TypedValue outValue, boolean resolveRefs)
+ @LayoutlibDelegate
+ static void getValue(Resources resources, String name, TypedValue outValue, boolean resolveRefs)
throws NotFoundException {
throw new UnsupportedOperationException();
}
- @Override
- public XmlResourceParser getXml(int id) throws NotFoundException {
- Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
+ @LayoutlibDelegate
+ static XmlResourceParser getXml(Resources resources, int id) throws NotFoundException {
+ Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);
if (value != null) {
String v = value.getSecond().getValue();
@@ -707,7 +720,8 @@
try {
XmlPullParser parser = ParserFactory.create(f);
- return new BridgeXmlBlockParser(parser, mContext, mPlatformResourceFlag[0]);
+ return new BridgeXmlBlockParser(parser, resources.mContext,
+ mPlatformResourceFlag[0]);
} catch (XmlPullParserException e) {
NotFoundException newE = new NotFoundException();
newE.initCause(e);
@@ -722,25 +736,31 @@
}
// id was not found or not resolved. Throw a NotFoundException.
- throwException(id);
+ throwException(resources, id);
// this is not used since the method above always throws
return null;
}
- @Override
- public XmlResourceParser loadXmlResourceParser(String file, int id,
+ @LayoutlibDelegate
+ static XmlResourceParser loadXmlResourceParser(Resources resources, int id,
+ String type) throws NotFoundException {
+ return resources.loadXmlResourceParser_Original(id, type);
+ }
+
+ @LayoutlibDelegate
+ static XmlResourceParser loadXmlResourceParser(Resources resources, String file, int id,
int assetCookie, String type) throws NotFoundException {
// even though we know the XML file to load directly, we still need to resolve the
// id so that we can know if it's a platform or project resource.
// (mPlatformResouceFlag will get the result and will be used later).
- getResourceValue(id, mPlatformResourceFlag);
+ getResourceValue(resources, id, mPlatformResourceFlag);
File f = new File(file);
try {
XmlPullParser parser = ParserFactory.create(f);
- return new BridgeXmlBlockParser(parser, mContext, mPlatformResourceFlag[0]);
+ return new BridgeXmlBlockParser(parser, resources.mContext, mPlatformResourceFlag[0]);
} catch (XmlPullParserException e) {
NotFoundException newE = new NotFoundException();
newE.initCause(e);
@@ -752,9 +772,9 @@
}
}
- @Override
- public InputStream openRawResource(int id) throws NotFoundException {
- Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
+ @LayoutlibDelegate
+ static InputStream openRawResource(Resources resources, int id) throws NotFoundException {
+ Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);
if (value != null) {
String path = value.getSecond().getValue();
@@ -781,15 +801,16 @@
}
// id was not found or not resolved. Throw a NotFoundException.
- throwException(id);
+ throwException(resources, id);
// this is not used since the method above always throws
return null;
}
- @Override
- public InputStream openRawResource(int id, TypedValue value) throws NotFoundException {
- getValue(id, value, true);
+ @LayoutlibDelegate
+ static InputStream openRawResource(Resources resources, int id, TypedValue value) throws
+ NotFoundException {
+ getValue(resources, id, value, true);
String path = value.string.toString();
@@ -813,23 +834,27 @@
throw new NotFoundException();
}
- @Override
- public AssetFileDescriptor openRawResourceFd(int id) throws NotFoundException {
+ @LayoutlibDelegate
+ static AssetFileDescriptor openRawResourceFd(Resources resources, int id) throws
+ NotFoundException {
throw new UnsupportedOperationException();
}
/**
- * Builds and throws a {@link Resources.NotFoundException} based on a resource id and a resource type.
+ * Builds and throws a {@link Resources.NotFoundException} based on a resource id and a resource
+ * type.
+ *
* @param id the id of the resource
+ *
* @throws NotFoundException
*/
- private void throwException(int id) throws NotFoundException {
+ private static void throwException(Resources resources, int id) throws NotFoundException {
// first get the String related to this id in the framework
Pair<ResourceType, String> resourceInfo = Bridge.resolveResourceId(id);
// if the name is unknown in the framework, get it from the custom view loader.
- if (resourceInfo == null && mLayoutlibCallback != null) {
- resourceInfo = mLayoutlibCallback.resolveResourceId(id);
+ if (resourceInfo == null && resources.mLayoutlibCallback != null) {
+ resourceInfo = resources.mLayoutlibCallback.resolveResourceId(id);
}
String message;
@@ -845,7 +870,7 @@
throw new NotFoundException(message);
}
- private int getInt(String v) throws NumberFormatException {
+ private static int getInt(String v) throws NumberFormatException {
int radix = 10;
if (v.startsWith("0x")) {
v = v.substring(2);
diff --git a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java
index 8d5863b..8bd2a7a 100644
--- a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java
@@ -23,7 +23,7 @@
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import android.annotation.Nullable;
-import android.content.res.BridgeResources.NinePatchInputStream;
+import com.android.layoutlib.bridge.util.NinePatchInputStream;
import android.graphics.BitmapFactory.Options;
import android.graphics.Bitmap_Delegate.BitmapCreateFlags;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 17ab2ff5..d1fd56a 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -52,11 +52,11 @@
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.content.res.BridgeAssetManager;
-import android.content.res.BridgeResources;
import android.content.res.BridgeTypedArray;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.Resources.Theme;
+import android.content.res.Resources_Delegate;
import android.database.DatabaseErrorHandler;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
@@ -224,7 +224,7 @@
public void initResources() {
AssetManager assetManager = AssetManager.getSystem();
- mSystemResources = BridgeResources.initSystem(
+ mSystemResources = Resources_Delegate.initSystem(
this,
assetManager,
mMetrics,
@@ -237,7 +237,7 @@
* Disposes the {@link Resources} singleton.
*/
public void disposeResources() {
- BridgeResources.disposeSystem();
+ Resources_Delegate.disposeSystem();
}
public void setBridgeInflater(BridgeInflater inflater) {
@@ -706,8 +706,8 @@
List<Pair<String, Boolean>> attributeList = searchAttrs(attrs);
- BridgeTypedArray ta = ((BridgeResources) mSystemResources).newTypeArray(attrs.length,
- isPlatformFile);
+ BridgeTypedArray ta =
+ Resources_Delegate.newTypeArray(mSystemResources, attrs.length, isPlatformFile);
// look for a custom style.
String customStyle = null;
@@ -941,7 +941,7 @@
List<Pair<String, Boolean>> attributes = searchAttrs(attrs);
- BridgeTypedArray ta = ((BridgeResources) mSystemResources).newTypeArray(attrs.length,
+ BridgeTypedArray ta = Resources_Delegate.newTypeArray(mSystemResources, attrs.length,
false);
// for each attribute, get its name so that we can search it in the style
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/NinePatchInputStream.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/NinePatchInputStream.java
new file mode 100644
index 0000000..96b795a
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/NinePatchInputStream.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.layoutlib.bridge.util;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+
+/**
+ * Simpler wrapper around FileInputStream. This is used when the input stream represent
+ * not a normal bitmap but a nine patch.
+ * This is useful when the InputStream is created in a method but used in another that needs
+ * to know whether this is 9-patch or not, such as BitmapFactory.
+ */
+public class NinePatchInputStream extends FileInputStream {
+ private boolean mFakeMarkSupport = true;
+ public NinePatchInputStream(File file) throws FileNotFoundException {
+ super(file);
+ }
+
+ @Override
+ public boolean markSupported() {
+ if (mFakeMarkSupport) {
+ // this is needed so that BitmapFactory doesn't wrap this in a BufferedInputStream.
+ return true;
+ }
+
+ return super.markSupported();
+ }
+
+ public void disableFakeMarkSupport() {
+ // disable fake mark support so that in case codec actually try to use them
+ // we don't lie to them.
+ mFakeMarkSupport = false;
+ }
+}
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java
index 5b99a6b..3b37612 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java
@@ -367,6 +367,10 @@
ClassVisitor cv = cw;
+ // FIXME Generify
+ if ("android/content/res/Resources".equals(className)) {
+ cv = new FieldInjectorAdapter(cv);
+ }
if (mReplaceMethodCallsClasses.contains(className)) {
cv = new ReplaceMethodCallsAdapter(cv, className);
}
@@ -445,4 +449,5 @@
}
return buffer.toByteArray();
}
+
}
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index 351be83..bd37665 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -155,6 +155,31 @@
*/
public final static String[] DELEGATE_METHODS = new String[] {
"android.app.Fragment#instantiate", //(Landroid/content/Context;Ljava/lang/String;Landroid/os/Bundle;)Landroid/app/Fragment;",
+ "android.content.res.Resources#getAnimation",
+ "android.content.res.Resources#getBoolean",
+ "android.content.res.Resources#getColor",
+ "android.content.res.Resources#getColorStateList",
+ "android.content.res.Resources#getDimension",
+ "android.content.res.Resources#getDimensionPixelOffset",
+ "android.content.res.Resources#getDimensionPixelSize",
+ "android.content.res.Resources#getDrawable",
+ "android.content.res.Resources#getIntArray",
+ "android.content.res.Resources#getInteger",
+ "android.content.res.Resources#getLayout",
+ "android.content.res.Resources#getResourceEntryName",
+ "android.content.res.Resources#getResourceName",
+ "android.content.res.Resources#getResourceTypeName",
+ "android.content.res.Resources#getString",
+ "android.content.res.Resources#getStringArray",
+ "android.content.res.Resources#getText",
+ "android.content.res.Resources#getTextArray",
+ "android.content.res.Resources#getValue",
+ "android.content.res.Resources#getXml",
+ "android.content.res.Resources#loadXmlResourceParser",
+ "android.content.res.Resources#obtainAttributes",
+ "android.content.res.Resources#obtainTypedArray",
+ "android.content.res.Resources#openRawResource",
+ "android.content.res.Resources#openRawResourceFd",
"android.content.res.Resources$Theme#obtainStyledAttributes",
"android.content.res.Resources$Theme#resolveAttribute",
"android.content.res.Resources$Theme#resolveAttributes",
@@ -316,7 +341,7 @@
// Use android.icu.text versions of DateFormat and SimpleDateFormat since the
// original ones do not match the Android implementation
"java.text.DateFormat", "android.icu.text.DateFormat",
- "java.text.SimpleDateFormat", "android.icu.text.SimpleDateFormat"
+ "java.text.SimpleDateFormat", "android.icu.text.SimpleDateFormat",
};
private final static String[] EXCLUDED_CLASSES =
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/FieldInjectorAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/FieldInjectorAdapter.java
new file mode 100644
index 0000000..4608a84
--- /dev/null
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/FieldInjectorAdapter.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.layoutlib.create;
+
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.Opcodes;
+
+/**
+ * Injects fields in a class.
+ * <p>
+ * TODO: Generify
+ */
+public class FieldInjectorAdapter extends ClassVisitor {
+ public FieldInjectorAdapter(ClassVisitor cv) {
+ super(Opcodes.ASM4, cv);
+ }
+
+ @Override
+ public void visitEnd() {
+ super.visitField(Opcodes.ACC_PUBLIC, "mLayoutlibCallback",
+ "Lcom/android/ide/common/rendering/api/LayoutlibCallback;", null, null);
+ super.visitField(Opcodes.ACC_PUBLIC, "mContext",
+ "Lcom/android/layoutlib/bridge/android/BridgeContext;", null, null);
+ super.visitEnd();
+ }
+}