aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2017-05-21 07:30:14 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2017-05-21 07:30:14 +0000
commit9dd04aeb909e03c82375e7a9439d624fd999fcba (patch)
treebf101c39f3a000faab5c87c58f5afb9c45797095
parentd1dcc2259c376d8e90f5ba65de68c7f4d0c68dcf (diff)
parentc56293b035c7a73188b709b7effc340a022e46f4 (diff)
downloadlayoutlib-9dd04aeb909e03c82375e7a9439d624fd999fcba.tar.gz
release-request-8aff77ce-b1d4-44c8-abb8-c39db5d1e998-for-git_oc-dr1-release-4029936 snap-temp-L09300000066301094
Change-Id: I61a7fbbfd86d14f7b7ed65618dc10530b43a2efc
-rw-r--r--.idea/modules.xml1
-rw-r--r--bridge/Android.mk3
-rw-r--r--bridge/bridge.iml1
-rw-r--r--bridge/src/android/content/res/BridgeTypedArray.java12
-rw-r--r--bridge/src/android/content/res/Resources_Delegate.java164
-rw-r--r--bridge/src/android/view/BridgeInflater.java10
-rw-r--r--bridge/src/com/android/layoutlib/bridge/BridgeConstants.java1
-rw-r--r--bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java66
-rw-r--r--bridge/src/com/android/layoutlib/bridge/android/support/RecyclerViewUtil.java6
-rw-r--r--bridge/tests/src/android/content/res/Resources_DelegateTest.java69
-rw-r--r--bridge/tests/src/com/android/layoutlib/bridge/intensive/RenderTests.java88
-rw-r--r--common/Android.mk27
-rw-r--r--common/common.iml11
-rw-r--r--common/src/com/android/tools/layoutlib/annotations/LayoutlibDelegate.java27
-rw-r--r--common/src/com/android/tools/layoutlib/annotations/Nullable.java35
-rw-r--r--common/src/com/android/tools/layoutlib/annotations/VisibleForTesting.java50
-rw-r--r--create/Android.mk3
-rw-r--r--create/create.iml1
-rw-r--r--create/src/com/android/tools/layoutlib/create/AsmGenerator.java4
-rw-r--r--create/src/com/android/tools/layoutlib/create/CreateInfo.java1
-rw-r--r--create/src/com/android/tools/layoutlib/create/FieldInjectorAdapter.java40
21 files changed, 483 insertions, 137 deletions
diff --git a/.idea/modules.xml b/.idea/modules.xml
index 6ffc1cc12b..4654a5c019 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -3,6 +3,7 @@
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/bridge/bridge.iml" filepath="$PROJECT_DIR$/bridge/bridge.iml" />
+ <module fileurl="file://$PROJECT_DIR$/common/common.iml" filepath="$PROJECT_DIR$/common/common.iml" />
<module fileurl="file://$PROJECT_DIR$/create/create.iml" filepath="$PROJECT_DIR$/create/create.iml" />
<module fileurl="file://$PROJECT_DIR$/legacy/legacy.iml" filepath="$PROJECT_DIR$/legacy/legacy.iml" />
<module fileurl="file://$PROJECT_DIR$/studio-custom-widgets/studio-android-widgets.iml" filepath="$PROJECT_DIR$/studio-custom-widgets/studio-android-widgets.iml" />
diff --git a/bridge/Android.mk b/bridge/Android.mk
index 3dd8002bcf..333e6bbc53 100644
--- a/bridge/Android.mk
+++ b/bridge/Android.mk
@@ -25,7 +25,8 @@ LOCAL_JAVA_LIBRARIES := \
LOCAL_STATIC_JAVA_LIBRARIES := \
temp_layoutlib \
- ninepatch-prebuilt
+ ninepatch-prebuilt \
+ layoutlib-common
LOCAL_MODULE := layoutlib
diff --git a/bridge/bridge.iml b/bridge/bridge.iml
index 45bb933996..90de760f41 100644
--- a/bridge/bridge.iml
+++ b/bridge/bridge.iml
@@ -88,5 +88,6 @@
<orderEntry type="library" scope="TEST" name="junit" level="project" />
<orderEntry type="library" scope="TEST" name="mockito" level="project" />
<orderEntry type="library" scope="TEST" name="objenesis" level="project" />
+ <orderEntry type="module" module-name="common" />
</component>
</module> \ No newline at end of file
diff --git a/bridge/src/android/content/res/BridgeTypedArray.java b/bridge/src/android/content/res/BridgeTypedArray.java
index b5996afd79..69242ac170 100644
--- a/bridge/src/android/content/res/BridgeTypedArray.java
+++ b/bridge/src/android/content/res/BridgeTypedArray.java
@@ -70,6 +70,7 @@ public final class BridgeTypedArray extends TypedArray {
private final BridgeContext mContext;
private final boolean mPlatformFile;
+ private final int[] mResourceId;
private final ResourceValue[] mResourceData;
private final String[] mNames;
private final boolean[] mIsFramework;
@@ -85,6 +86,7 @@ public final class BridgeTypedArray extends TypedArray {
mBridgeResources = resources;
mContext = context;
mPlatformFile = platformFile;
+ mResourceId = new int[len];
mResourceData = new ResourceValue[len];
mNames = new String[len];
mIsFramework = new boolean[len];
@@ -95,9 +97,12 @@ public final class BridgeTypedArray extends TypedArray {
* @param index the index of the value in the TypedArray
* @param name the name of the attribute
* @param isFramework whether the attribute is in the android namespace.
+ * @param resourceId the reference id of this resource
* @param value the value of the attribute
*/
- public void bridgeSetValue(int index, String name, boolean isFramework, ResourceValue value) {
+ public void bridgeSetValue(int index, String name, boolean isFramework, int resourceId,
+ ResourceValue value) {
+ mResourceId[index] = resourceId;
mResourceData[index] = value;
mNames[index] = name;
mIsFramework[index] = isFramework;
@@ -105,7 +110,7 @@ public final class BridgeTypedArray extends TypedArray {
/**
* Seals the array after all calls to
- * {@link #bridgeSetValue(int, String, boolean, ResourceValue)} have been done.
+ * {@link #bridgeSetValue(int, String, boolean, int, ResourceValue)} have been done.
* <p/>This allows to compute the list of non default values, permitting
* {@link #getIndexCount()} to return the proper value.
*/
@@ -788,6 +793,9 @@ public final class BridgeTypedArray extends TypedArray {
case TYPE_STRING:
outValue.string = getString(index);
return true;
+ case TYPE_REFERENCE:
+ outValue.resourceId = mResourceId[index];
+ return true;
default:
// For back-compatibility, parse as float.
String s = getString(index);
diff --git a/bridge/src/android/content/res/Resources_Delegate.java b/bridge/src/android/content/res/Resources_Delegate.java
index e57523d54f..0a5912974f 100644
--- a/bridge/src/android/content/res/Resources_Delegate.java
+++ b/bridge/src/android/content/res/Resources_Delegate.java
@@ -33,7 +33,9 @@ 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.resources.ResourceUrl;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+import com.android.tools.layoutlib.annotations.VisibleForTesting;
import com.android.util.Pair;
import org.xmlpull.v1.XmlPullParser;
@@ -58,41 +60,70 @@ import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.Iterator;
+import java.util.Objects;
+import java.util.WeakHashMap;
+
+import static com.android.SdkConstants.ANDROID_PKG;
+import static com.android.SdkConstants.PREFIX_RESOURCE_REF;
@SuppressWarnings("deprecation")
public class Resources_Delegate {
+ private static WeakHashMap<Resources, LayoutlibCallback> sLayoutlibCallbacks = new
+ WeakHashMap<>();
+ private static WeakHashMap<Resources, BridgeContext> sContexts = new
+ WeakHashMap<>();
private static boolean[] mPlatformResourceFlag = new boolean[1];
// TODO: This cache is cleared every time a render session is disposed. Look into making this
// more long lived.
private static LruCache<String, Drawable.ConstantState> sDrawableCache = new LruCache<>(50);
- public static Resources initSystem(BridgeContext context,
- AssetManager assets,
- DisplayMetrics metrics,
- Configuration config,
- LayoutlibCallback layoutlibCallback) {
+ public static Resources initSystem(@NonNull BridgeContext context,
+ @NonNull AssetManager assets,
+ @NonNull DisplayMetrics metrics,
+ @NonNull Configuration config,
+ @NonNull LayoutlibCallback layoutlibCallback) {
+ assert Resources.mSystem == null :
+ "Resources_Delegate.initSystem called twice before disposeSystem was called";
Resources resources = new Resources(Resources_Delegate.class.getClassLoader());
resources.setImpl(new ResourcesImpl(assets, metrics, config, new DisplayAdjustments()));
- resources.mContext = context;
- resources.mLayoutlibCallback = layoutlibCallback;
+ sContexts.put(resources, Objects.requireNonNull(context));
+ sLayoutlibCallbacks.put(resources, Objects.requireNonNull(layoutlibCallback));
return Resources.mSystem = resources;
}
+ /** Returns the {@link BridgeContext} associated to the given {@link Resources} */
+ @VisibleForTesting
+ @NonNull
+ public static BridgeContext getContext(@NonNull Resources resources) {
+ assert sContexts.containsKey(resources) :
+ "Resources_Delegate.getContext called before initSystem";
+ return sContexts.get(resources);
+ }
+
+ /** Returns the {@link LayoutlibCallback} associated to the given {@link Resources} */
+ @VisibleForTesting
+ @NonNull
+ public static LayoutlibCallback getLayoutlibCallback(@NonNull Resources resources) {
+ assert sLayoutlibCallbacks.containsKey(resources) :
+ "Resources_Delegate.getLayoutlibCallback called before initSystem";
+ return sLayoutlibCallbacks.get(resources);
+ }
+
/**
* 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() {
sDrawableCache.evictAll();
- Resources.mSystem.mContext = null;
- Resources.mSystem.mLayoutlibCallback = null;
+ sContexts.clear();
+ sLayoutlibCallbacks.clear();
Resources.mSystem = null;
}
public static BridgeTypedArray newTypeArray(Resources resources, int numEntries,
boolean platformFile) {
- return new BridgeTypedArray(resources, resources.mContext, numEntries, platformFile);
+ return new BridgeTypedArray(resources, getContext(resources), numEntries, platformFile);
}
private static Pair<ResourceType, String> getResourceInfo(Resources resources, int id,
@@ -100,10 +131,12 @@ public class Resources_Delegate {
// first get the String related to this id in the framework
Pair<ResourceType, String> resourceInfo = Bridge.resolveResourceId(id);
+ assert Resources.mSystem != null : "Resources_Delegate.initSystem wasn't called";
// 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 (resources != Resources.mSystem &&
+ (!sContexts.containsKey(resources) || !sLayoutlibCallbacks.containsKey(resources))) {
+ sLayoutlibCallbacks.put(resources, getLayoutlibCallback(Resources.mSystem));
+ sContexts.put(resources, getContext(Resources.mSystem));
}
if (resourceInfo != null) {
@@ -112,13 +145,11 @@ public class Resources_Delegate {
}
// didn't find a match in the framework? look in the project.
- if (resources.mLayoutlibCallback != null) {
- resourceInfo = resources.mLayoutlibCallback.resolveResourceId(id);
+ resourceInfo = getLayoutlibCallback(resources).resolveResourceId(id);
- if (resourceInfo != null) {
- platformResFlag_out[0] = false;
- return resourceInfo;
- }
+ if (resourceInfo != null) {
+ platformResFlag_out[0] = false;
+ return resourceInfo;
}
return null;
}
@@ -130,7 +161,7 @@ public class Resources_Delegate {
if (resourceInfo != null) {
String attributeName = resourceInfo.getSecond();
- RenderResources renderResources = resources.mContext.getRenderResources();
+ RenderResources renderResources = getContext(resources).getRenderResources();
ResourceValue value = platformResFlag_out[0] ?
renderResources.getFrameworkResource(resourceInfo.getFirst(), attributeName) :
renderResources.getProjectResource(resourceInfo.getFirst(), attributeName);
@@ -163,7 +194,7 @@ public class Resources_Delegate {
drawable = constantState.newDrawable(resources, theme);
} else {
drawable =
- ResourceHelper.getDrawable(value.getSecond(), resources.mContext, theme);
+ ResourceHelper.getDrawable(value.getSecond(), getContext(resources), theme);
if (key != null) {
sDrawableCache.put(key, drawable.getConstantState());
@@ -228,7 +259,7 @@ public class Resources_Delegate {
if (resValue != null) {
ColorStateList stateList = ResourceHelper.getColorStateList(resValue.getSecond(),
- resources.mContext);
+ getContext(resources));
if (stateList != null) {
return stateList.obtainForTheme(theme);
}
@@ -410,11 +441,11 @@ public class Resources_Delegate {
@NonNull
private static String resolveReference(Resources resources, @NonNull String ref,
boolean forceFrameworkOnly) {
- if (ref.startsWith(SdkConstants.PREFIX_RESOURCE_REF) || ref.startsWith
+ if (ref.startsWith(PREFIX_RESOURCE_REF) || ref.startsWith
(SdkConstants.PREFIX_THEME_REF)) {
ResourceValue rv =
- resources.mContext.getRenderResources().findResValue(ref, forceFrameworkOnly);
- rv = resources.mContext.getRenderResources().resolveResValue(rv);
+ getContext(resources).getRenderResources().findResValue(ref, forceFrameworkOnly);
+ rv = getContext(resources).getRenderResources().resolveResValue(rv);
if (rv != null) {
return rv.getValue();
}
@@ -434,7 +465,7 @@ public class Resources_Delegate {
try {
// check if the current parser can provide us with a custom parser.
if (!mPlatformResourceFlag[0]) {
- parser = resources.mLayoutlibCallback.getParser(value);
+ parser = getLayoutlibCallback(resources).getParser(value);
}
// create a new one manually if needed.
@@ -448,7 +479,7 @@ public class Resources_Delegate {
}
if (parser != null) {
- return new BridgeXmlBlockParser(parser, resources.mContext,
+ return new BridgeXmlBlockParser(parser, getContext(resources),
mPlatformResourceFlag[0]);
}
} catch (XmlPullParserException e) {
@@ -483,7 +514,7 @@ public class Resources_Delegate {
// give that to our XmlBlockParser
parser = ParserFactory.create(xml);
- return new BridgeXmlBlockParser(parser, resources.mContext,
+ return new BridgeXmlBlockParser(parser, getContext(resources),
mPlatformResourceFlag[0]);
}
} catch (XmlPullParserException e) {
@@ -505,7 +536,7 @@ public class Resources_Delegate {
@LayoutlibDelegate
static TypedArray obtainAttributes(Resources resources, AttributeSet set, int[] attrs) {
- return resources.mContext.obtainStyledAttributes(set, attrs);
+ return getContext(resources).obtainStyledAttributes(set, attrs);
}
@LayoutlibDelegate
@@ -680,7 +711,7 @@ public class Resources_Delegate {
if (platformOut[0]) {
packageName = SdkConstants.ANDROID_NS_NAME;
} else {
- packageName = resources.mContext.getPackageName();
+ packageName = getContext(resources).getPackageName();
packageName = packageName == null ? SdkConstants.APP_PREFIX : packageName;
}
return packageName + ':' + resourceInfo.getFirst().getName() + '/' +
@@ -698,7 +729,7 @@ public class Resources_Delegate {
if (platformOut[0]) {
return SdkConstants.ANDROID_NS_NAME;
}
- String packageName = resources.mContext.getPackageName();
+ String packageName = getContext(resources).getPackageName();
return packageName == null ? SdkConstants.APP_PREFIX : packageName;
}
throwException(resid, null);
@@ -793,7 +824,7 @@ public class Resources_Delegate {
NotFoundException {
Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);
if (value != null) {
- return ResourceHelper.getFont(value.getSecond(), resources.mContext, null);
+ return ResourceHelper.getFont(value.getSecond(), getContext(resources), null);
}
throwException(resources, id);
@@ -807,7 +838,7 @@ public class Resources_Delegate {
NotFoundException {
Resources_Delegate.getValue(resources, id, outValue, true);
if (outValue.string != null) {
- return ResourceHelper.getFont(outValue.string.toString(), resources.mContext, null,
+ return ResourceHelper.getFont(outValue.string.toString(), getContext(resources), null,
mPlatformResourceFlag[0]);
}
@@ -867,7 +898,7 @@ public class Resources_Delegate {
try {
XmlPullParser parser = ParserFactory.create(f);
- return new BridgeXmlBlockParser(parser, resources.mContext,
+ return new BridgeXmlBlockParser(parser, getContext(resources),
mPlatformResourceFlag[0]);
} catch (XmlPullParserException e) {
NotFoundException newE = new NotFoundException();
@@ -907,7 +938,7 @@ public class Resources_Delegate {
try {
XmlPullParser parser = ParserFactory.create(f);
- return new BridgeXmlBlockParser(parser, resources.mContext, mPlatformResourceFlag[0]);
+ return new BridgeXmlBlockParser(parser, getContext(resources), mPlatformResourceFlag[0]);
} catch (XmlPullParserException e) {
NotFoundException newE = new NotFoundException();
newE.initCause(e);
@@ -987,6 +1018,69 @@ public class Resources_Delegate {
throw new UnsupportedOperationException();
}
+ @VisibleForTesting
+ @Nullable
+ static ResourceUrl resourceUrlFromName(@NonNull String name, @Nullable String defType,
+ @Nullable
+ String defPackage) {
+ int colonIdx = name.indexOf(':');
+ int slashIdx = name.indexOf('/');
+
+ if (colonIdx != -1 && slashIdx != -1) {
+ // Easy case
+ return ResourceUrl.parse(PREFIX_RESOURCE_REF + name);
+ }
+
+ if (colonIdx == -1 && slashIdx == -1) {
+ if (defType == null) {
+ throw new IllegalArgumentException("name does not define a type an no defType was" +
+ " passed");
+ }
+
+ // It does not define package or type
+ return ResourceUrl.parse(
+ PREFIX_RESOURCE_REF + (defPackage != null ? defPackage + ":" : "") + defType +
+ "/" + name);
+ }
+
+ if (colonIdx != -1) {
+ if (defType == null) {
+ throw new IllegalArgumentException("name does not define a type an no defType was" +
+ " passed");
+ }
+ // We have package but no type
+ String pkg = name.substring(0, colonIdx);
+ ResourceType type = ResourceType.getEnum(defType);
+ return type != null ? ResourceUrl.create(pkg, type, name.substring(colonIdx + 1)) :
+ null;
+ }
+
+ ResourceType type = ResourceType.getEnum(name.substring(0, slashIdx));
+ if (type == null) {
+ return null;
+ }
+ // We have type but no package
+ return ResourceUrl.create(defPackage,
+ type,
+ name.substring(slashIdx + 1));
+ }
+
+ @LayoutlibDelegate
+ static int getIdentifier(Resources resources, String name, String defType, String defPackage) {
+ if (name == null) {
+ return 0;
+ }
+
+ ResourceUrl url = resourceUrlFromName(name, defType, defPackage);
+ Integer id = null;
+ if (url != null) {
+ id = ANDROID_PKG.equals(url.namespace) ? Bridge.getResourceId(url.type, url.name) :
+ getLayoutlibCallback(resources).getResourceId(url.type, url.name);
+ }
+
+ return id != null ? id : 0;
+ }
+
/**
* Builds and throws a {@link Resources.NotFoundException} based on a resource id and a resource
* type.
diff --git a/bridge/src/android/view/BridgeInflater.java b/bridge/src/android/view/BridgeInflater.java
index b6e6ec0084..58d8c52746 100644
--- a/bridge/src/android/view/BridgeInflater.java
+++ b/bridge/src/android/view/BridgeInflater.java
@@ -370,10 +370,12 @@ public final class BridgeInflater extends LayoutInflater {
}
if (ReflectionUtils.isInstanceOf(view, RecyclerViewUtil.CN_RECYCLER_VIEW)) {
Integer resourceId = null;
- String attrVal = attrs.getAttributeValue(BridgeConstants.NS_TOOLS_URI,
+ String attrListItemValue = attrs.getAttributeValue(BridgeConstants.NS_TOOLS_URI,
BridgeConstants.ATTR_LIST_ITEM);
- if (attrVal != null && !attrVal.isEmpty()) {
- ResourceValue resValue = bc.getRenderResources().findResValue(attrVal, false);
+ int attrItemCountValue = attrs.getAttributeIntValue(BridgeConstants.NS_TOOLS_URI,
+ BridgeConstants.ATTR_ITEM_COUNT, -1);
+ if (attrListItemValue != null && !attrListItemValue.isEmpty()) {
+ ResourceValue resValue = bc.getRenderResources().findResValue(attrListItemValue, false);
if (resValue.isFramework()) {
resourceId = Bridge.getResourceId(resValue.getResourceType(),
resValue.getName());
@@ -385,7 +387,7 @@ public final class BridgeInflater extends LayoutInflater {
if (resourceId == null) {
resourceId = 0;
}
- RecyclerViewUtil.setAdapter(view, bc, mLayoutlibCallback, resourceId);
+ RecyclerViewUtil.setAdapter(view, bc, mLayoutlibCallback, resourceId, attrItemCountValue);
} else if (ReflectionUtils.isInstanceOf(view, DrawerLayoutUtil.CN_DRAWER_LAYOUT)) {
String attrVal = attrs.getAttributeValue(BridgeConstants.NS_TOOLS_URI,
BridgeConstants.ATTR_OPEN_DRAWER);
diff --git a/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java b/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java
index 6228766957..d95c5088c9 100644
--- a/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java
+++ b/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java
@@ -55,4 +55,5 @@ public class BridgeConstants {
@SuppressWarnings("SpellCheckingInspection")
public static final String ATTR_LIST_ITEM = "listitem";
public static final String ATTR_OPEN_DRAWER = "openDrawer";
+ public static final String ATTR_ITEM_COUNT = "itemCount";
}
diff --git a/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 8bd924ea9c..1f0a04f1cb 100644
--- a/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -212,11 +212,11 @@ public class BridgeContext extends Context {
* @param config the Configuration object for this render.
* @param targetSdkVersion the targetSdkVersion of the application.
*/
- public BridgeContext(Object projectKey, DisplayMetrics metrics,
- RenderResources renderResources,
- AssetRepository assets,
- LayoutlibCallback layoutlibCallback,
- Configuration config,
+ public BridgeContext(Object projectKey, @NonNull DisplayMetrics metrics,
+ @NonNull RenderResources renderResources,
+ @NonNull AssetRepository assets,
+ @NonNull LayoutlibCallback layoutlibCallback,
+ @NonNull Configuration config,
int targetSdkVersion,
boolean hasRtlSupport) {
mProjectKey = projectKey;
@@ -750,7 +750,7 @@ public class BridgeContext extends Context {
return null;
}
- List<Pair<String, Boolean>> attributeList = searchAttrs(attrs);
+ List<AttributeHolder> attributeList = searchAttrs(attrs);
BridgeTypedArray ta =
Resources_Delegate.newTypeArray(mSystemResources, attrs.length, isPlatformFile);
@@ -866,14 +866,14 @@ public class BridgeContext extends Context {
if (attributeList != null) {
for (int index = 0 ; index < attributeList.size() ; index++) {
- Pair<String, Boolean> attribute = attributeList.get(index);
+ AttributeHolder attributeHolder = attributeList.get(index);
- if (attribute == null) {
+ if (attributeHolder == null) {
continue;
}
- String attrName = attribute.getFirst();
- boolean frameworkAttr = attribute.getSecond();
+ String attrName = attributeHolder.name;
+ boolean frameworkAttr = attributeHolder.isFramework;
String value = null;
if (set != null) {
value = set.getAttributeValue(
@@ -965,11 +965,12 @@ public class BridgeContext extends Context {
}
}
- ta.bridgeSetValue(index, attrName, frameworkAttr, defaultValue);
+ ta.bridgeSetValue(index, attrName, frameworkAttr, attributeHolder.resourceId,
+ defaultValue);
} else {
// there is a value in the XML, but we need to resolve it in case it's
// referencing another resource or a theme value.
- ta.bridgeSetValue(index, attrName, frameworkAttr,
+ ta.bridgeSetValue(index, attrName, frameworkAttr, attributeHolder.resourceId,
mRenderResources.resolveValue(null, attrName, value, isPlatformFile));
}
}
@@ -1013,7 +1014,7 @@ public class BridgeContext extends Context {
*/
private Pair<BridgeTypedArray, PropertiesMap> createStyleBasedTypedArray(
@Nullable StyleResourceValue style, int[] attrs) throws Resources.NotFoundException {
- List<Pair<String, Boolean>> attributes = searchAttrs(attrs);
+ List<AttributeHolder> attributes = searchAttrs(attrs);
BridgeTypedArray ta =
Resources_Delegate.newTypeArray(mSystemResources, attrs.length, false);
@@ -1021,13 +1022,13 @@ public class BridgeContext extends Context {
PropertiesMap defaultPropMap = new PropertiesMap();
// for each attribute, get its name so that we can search it in the style
for (int i = 0; i < attrs.length; i++) {
- Pair<String, Boolean> attribute = attributes.get(i);
+ AttributeHolder attrHolder = attributes.get(i);
- if (attribute != null) {
+ if (attrHolder != null) {
// look for the value in the given style
ResourceValue resValue;
- String attrName = attribute.getFirst();
- boolean frameworkAttr = attribute.getSecond();
+ String attrName = attrHolder.name;
+ boolean frameworkAttr = attrHolder.isFramework;
if (style != null) {
resValue = mRenderResources.findItemInStyle(style, attrName, frameworkAttr);
} else {
@@ -1039,7 +1040,8 @@ public class BridgeContext extends Context {
String preResolve = resValue.getValue();
// resolve it to make sure there are no references left.
resValue = mRenderResources.resolveResValue(resValue);
- ta.bridgeSetValue(i, attrName, frameworkAttr, resValue);
+ ta.bridgeSetValue(i, attrName, frameworkAttr, attrHolder.resourceId,
+ resValue);
defaultPropMap.put(
frameworkAttr ? SdkConstants.ANDROID_PREFIX + attrName : attrName,
new Property(preResolve, resValue.getValue()));
@@ -1053,28 +1055,28 @@ public class BridgeContext extends Context {
}
/**
- * The input int[] attrs is a list of attributes. The returns a list of information about
+ * The input int[] attributeIds is a list of attributes. The returns a list of information about
* each attributes. The information is (name, isFramework)
* <p/>
*
- * @param attrs An attribute array reference given to obtainStyledAttributes.
+ * @param attributeIds An attribute array reference given to obtainStyledAttributes.
* @return List of attribute information.
*/
- private List<Pair<String, Boolean>> searchAttrs(int[] attrs) {
- List<Pair<String, Boolean>> results = new ArrayList<>(attrs.length);
+ private List<AttributeHolder> searchAttrs(int[] attributeIds) {
+ List<AttributeHolder> results = new ArrayList<>(attributeIds.length);
// for each attribute, get its name so that we can search it in the style
- for (int attr : attrs) {
- Pair<ResourceType, String> resolvedResource = Bridge.resolveResourceId(attr);
+ for (int id : attributeIds) {
+ Pair<ResourceType, String> resolvedResource = Bridge.resolveResourceId(id);
boolean isFramework = false;
if (resolvedResource != null) {
isFramework = true;
} else {
- resolvedResource = mLayoutlibCallback.resolveResourceId(attr);
+ resolvedResource = mLayoutlibCallback.resolveResourceId(id);
}
if (resolvedResource != null) {
- results.add(Pair.of(resolvedResource.getSecond(), isFramework));
+ results.add(new AttributeHolder(id, resolvedResource.getSecond(), isFramework));
} else {
results.add(null);
}
@@ -2008,6 +2010,18 @@ public class BridgeContext extends Context {
return false;
}
+ private class AttributeHolder {
+ private int resourceId;
+ private String name;
+ private boolean isFramework;
+
+ private AttributeHolder(int resourceId, String name, boolean isFramework) {
+ this.resourceId = resourceId;
+ this.name = name;
+ this.isFramework = isFramework;
+ }
+ }
+
/**
* The cached value depends on
* <ol>
diff --git a/bridge/src/com/android/layoutlib/bridge/android/support/RecyclerViewUtil.java b/bridge/src/com/android/layoutlib/bridge/android/support/RecyclerViewUtil.java
index ab278195f3..c6e034f4a4 100644
--- a/bridge/src/com/android/layoutlib/bridge/android/support/RecyclerViewUtil.java
+++ b/bridge/src/com/android/layoutlib/bridge/android/support/RecyclerViewUtil.java
@@ -55,13 +55,17 @@ public class RecyclerViewUtil {
* Any exceptions thrown during the process are logged in {@link Bridge#getLog()}
*/
public static void setAdapter(@NonNull View recyclerView, @NonNull BridgeContext context,
- @NonNull LayoutlibCallback layoutlibCallback, int adapterLayout) {
+ @NonNull LayoutlibCallback layoutlibCallback, int adapterLayout, int itemCount) {
try {
setLayoutManager(recyclerView, context, layoutlibCallback);
Object adapter = createAdapter(layoutlibCallback);
if (adapter != null) {
setProperty(recyclerView, CN_ADAPTER, adapter, "setAdapter");
setProperty(adapter, int.class, adapterLayout, "setLayoutId");
+
+ if (itemCount != -1) {
+ setProperty(adapter, int.class, itemCount, "setItemCount");
+ }
}
} catch (ReflectionException e) {
Throwable cause = getCause(e);
diff --git a/bridge/tests/src/android/content/res/Resources_DelegateTest.java b/bridge/tests/src/android/content/res/Resources_DelegateTest.java
new file mode 100644
index 0000000000..be39ab0712
--- /dev/null
+++ b/bridge/tests/src/android/content/res/Resources_DelegateTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2017 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 android.content.res;
+
+import com.android.resources.ResourceType;
+import com.android.resources.ResourceUrl;
+
+import org.junit.Test;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+public class Resources_DelegateTest {
+ private static void assertResourceUrl(@Nullable String pkg, @NonNull String name,
+ @NonNull ResourceType type, @Nullable ResourceUrl url) {
+ assertNotNull(url);
+ assertEquals(type, url.type);
+ assertEquals(pkg, url.namespace);
+ assertEquals(name, url.name);
+ }
+
+ @Test
+ public void resourceUrlFromName() {
+ try {
+ Resources_Delegate.resourceUrlFromName("pkg:name", null, null);
+ fail("Expected IllegalArgumentException since no type was defined");
+ } catch (IllegalArgumentException ignored) {
+ }
+
+ assertNull(Resources_Delegate.resourceUrlFromName("package:invalid/name", null, null));
+ assertNull(Resources_Delegate.resourceUrlFromName("package:name", "invalid", null));
+ assertResourceUrl("package", "name", ResourceType.ID,
+ Resources_Delegate.resourceUrlFromName("package:name", "id", null));
+ assertResourceUrl("package", "name", ResourceType.ID,
+ Resources_Delegate.resourceUrlFromName("name", "id", "package"));
+ assertResourceUrl("package", "test", ResourceType.STRING,
+ Resources_Delegate.resourceUrlFromName("package:string/test", null, null));
+ assertResourceUrl(null, "test", ResourceType.STRING,
+ Resources_Delegate.resourceUrlFromName("string/test", null, null));
+
+
+ // Type and package in the name take precedence over the passed defType and defPackage
+ assertResourceUrl("p1", "r1", ResourceType.STRING,
+ Resources_Delegate.resourceUrlFromName("p1:string/r1", "id", "p2"));
+ assertResourceUrl("p2", "r1", ResourceType.STRING,
+ Resources_Delegate.resourceUrlFromName("string/r1", "id", "p2"));
+ assertResourceUrl("p1", "r1", ResourceType.ID,
+ Resources_Delegate.resourceUrlFromName("p1:r1", "id", "p2"));
+ }
+} \ No newline at end of file
diff --git a/bridge/tests/src/com/android/layoutlib/bridge/intensive/RenderTests.java b/bridge/tests/src/com/android/layoutlib/bridge/intensive/RenderTests.java
index 833652a3a6..208c2d7030 100644
--- a/bridge/tests/src/com/android/layoutlib/bridge/intensive/RenderTests.java
+++ b/bridge/tests/src/com/android/layoutlib/bridge/intensive/RenderTests.java
@@ -20,6 +20,7 @@ import com.android.ide.common.rendering.api.RenderSession;
import com.android.ide.common.rendering.api.SessionParams;
import com.android.ide.common.rendering.api.SessionParams.RenderingMode;
import com.android.ide.common.rendering.api.ViewInfo;
+import com.android.internal.R;
import com.android.layoutlib.bridge.android.BridgeContext;
import com.android.layoutlib.bridge.android.RenderParamsFlags;
import com.android.layoutlib.bridge.impl.RenderAction;
@@ -35,6 +36,7 @@ import org.junit.Test;
import android.content.res.AssetManager;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.content.res.Resources_Delegate;
import android.util.DisplayMetrics;
import android.util.TypedValue;
@@ -47,6 +49,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
/**
@@ -412,26 +415,28 @@ public class RenderTests extends RenderTestBase {
AssetManager assetManager = AssetManager.getSystem();
DisplayMetrics metrics = new DisplayMetrics();
Configuration configuration = RenderAction.getConfiguration(params);
- //noinspection deprecation
- Resources resources = new Resources(assetManager, metrics, configuration);
- resources.mLayoutlibCallback = params.getLayoutlibCallback();
- resources.mContext =
- new BridgeContext(params.getProjectKey(), metrics, params.getResources(),
- params.getAssets(), params.getLayoutlibCallback(), configuration,
- params.getTargetSdkVersion(), params.isRtlSupported());
+ BridgeContext context = new BridgeContext(params.getProjectKey(), metrics, params.getResources(),
+ params.getAssets(), params.getLayoutlibCallback(), configuration,
+ params.getTargetSdkVersion(), params.isRtlSupported());
+ Resources resources = Resources_Delegate.initSystem(context, assetManager, metrics,
+ configuration, params.getLayoutlibCallback());
// Test
assertEquals("android:style/ButtonBar",
resources.getResourceName(android.R.style.ButtonBar));
assertEquals("android", resources.getResourcePackageName(android.R.style.ButtonBar));
assertEquals("ButtonBar", resources.getResourceEntryName(android.R.style.ButtonBar));
assertEquals("style", resources.getResourceTypeName(android.R.style.ButtonBar));
- int id = resources.mLayoutlibCallback.getResourceId(ResourceType.STRING, "app_name");
+ int id = Resources_Delegate.getLayoutlibCallback(resources).getResourceId(
+ ResourceType.STRING,
+ "app_name");
assertEquals("com.android.layoutlib.test.myapplication:string/app_name",
resources.getResourceName(id));
assertEquals("com.android.layoutlib.test.myapplication",
resources.getResourcePackageName(id));
assertEquals("string", resources.getResourceTypeName(id));
assertEquals("app_name", resources.getResourceEntryName(id));
+
+ context.disposeResources();
}
@Test
@@ -449,20 +454,22 @@ public class RenderTests extends RenderTestBase {
AssetManager assetManager = AssetManager.getSystem();
DisplayMetrics metrics = new DisplayMetrics();
Configuration configuration = RenderAction.getConfiguration(params);
- //noinspection deprecation
- Resources resources = new Resources(assetManager, metrics, configuration);
- resources.mLayoutlibCallback = params.getLayoutlibCallback();
- resources.mContext =
- new BridgeContext(params.getProjectKey(), metrics, params.getResources(),
- params.getAssets(), params.getLayoutlibCallback(), configuration,
- params.getTargetSdkVersion(), params.isRtlSupported());
-
- int id = resources.mLayoutlibCallback.getResourceId(ResourceType.ARRAY, "string_array");
+ BridgeContext context = new BridgeContext(params.getProjectKey(), metrics, params.getResources(),
+ params.getAssets(), params.getLayoutlibCallback(), configuration,
+ params.getTargetSdkVersion(), params.isRtlSupported());
+ Resources resources = Resources_Delegate.initSystem(context, assetManager, metrics,
+ configuration, params.getLayoutlibCallback());
+
+ int id = Resources_Delegate.getLayoutlibCallback(resources).getResourceId(
+ ResourceType.ARRAY,
+ "string_array");
String[] strings = resources.getStringArray(id);
assertArrayEquals(
new String[]{"mystring", "Hello world!", "candidates", "Unknown", "?EC"},
strings);
assertTrue(sRenderMessages.isEmpty());
+
+ context.disposeResources();
}
@Test
@@ -509,19 +516,16 @@ public class RenderTests extends RenderTestBase {
layoutLibCallback.initResources();
SessionParams params = getSessionParams(parser, ConfigGenerator.NEXUS_4,
layoutLibCallback, "AppTheme", true, RenderingMode.NORMAL, 22);
- AssetManager assetManager = AssetManager.getSystem();
DisplayMetrics metrics = new DisplayMetrics();
Configuration configuration = RenderAction.getConfiguration(params);
- //noinspection deprecation
- Resources resources = new Resources(assetManager, metrics, configuration);
- resources.mLayoutlibCallback = params.getLayoutlibCallback();
- resources.mContext =
+
+ BridgeContext mContext =
new BridgeContext(params.getProjectKey(), metrics, params.getResources(),
params.getAssets(), params.getLayoutlibCallback(), configuration,
params.getTargetSdkVersion(), params.isRtlSupported());
TypedValue outValue = new TypedValue();
- resources.mContext.resolveThemeAttribute(android.R.attr.colorPrimary, outValue, true);
+ mContext.resolveThemeAttribute(android.R.attr.colorPrimary, outValue, true);
assertEquals(TypedValue.TYPE_INT_COLOR_ARGB8, outValue.type);
assertNotEquals(0, outValue.data);
assertTrue(sRenderMessages.isEmpty());
@@ -531,4 +535,42 @@ public class RenderTests extends RenderTestBase {
public void testRectangleShadow() throws Exception {
renderAndVerify("shadows_test.xml", "shadows_test.png");
}
+
+ @Test
+ public void testResourcesGetIdentifier() throws Exception {
+ // Setup
+ // Create the layout pull parser for our resources (empty.xml can not be part of the test
+ // app as it won't compile).
+ LayoutPullParser parser = LayoutPullParser.createFromPath("/empty.xml");
+ // Create LayoutLibCallback.
+ LayoutLibTestCallback layoutLibCallback =
+ new LayoutLibTestCallback(getLogger(), mDefaultClassLoader);
+ layoutLibCallback.initResources();
+ SessionParams params = getSessionParams(parser, ConfigGenerator.NEXUS_4,
+ layoutLibCallback, "AppTheme", true, RenderingMode.NORMAL, 22);
+ AssetManager assetManager = AssetManager.getSystem();
+ DisplayMetrics metrics = new DisplayMetrics();
+ Configuration configuration = RenderAction.getConfiguration(params);
+ BridgeContext context = new BridgeContext(params.getProjectKey(), metrics, params.getResources(),
+ params.getAssets(), params.getLayoutlibCallback(), configuration,
+ params.getTargetSdkVersion(), params.isRtlSupported());
+ Resources resources = Resources_Delegate.initSystem(context, assetManager, metrics,
+ configuration, params.getLayoutlibCallback());
+ int id = Resources_Delegate.getLayoutlibCallback(resources).getResourceId(
+ ResourceType.STRING,
+ "app_name");
+ assertEquals(id, resources.getIdentifier("string/app_name", null, null));
+ assertEquals(id, resources.getIdentifier("app_name", "string", null));
+ assertEquals(0, resources.getIdentifier("string/does_not_exist", null, null));
+ assertEquals(R.string.accept, resources.getIdentifier("android:string/accept", null,
+ null));
+ assertEquals(R.string.accept, resources.getIdentifier("string/accept", null,
+ "android"));
+ assertEquals(R.id.message, resources.getIdentifier("id/message", null,
+ "android"));
+ assertEquals(R.string.accept, resources.getIdentifier("accept", "string",
+ "android"));
+
+ context.disposeResources();
+ }
}
diff --git a/common/Android.mk b/common/Android.mk
new file mode 100644
index 0000000000..5e22fddfe4
--- /dev/null
+++ b/common/Android.mk
@@ -0,0 +1,27 @@
+#
+# Copyright (C) 2008 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.
+#
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under,src)
+
+LOCAL_MODULE := layoutlib-common
+
+include $(BUILD_HOST_JAVA_LIBRARY)
+
+# Build all sub-directories
+include $(call all-makefiles-under,$(LOCAL_PATH))
+
diff --git a/common/common.iml b/common/common.iml
new file mode 100644
index 0000000000..c90834f2d6
--- /dev/null
+++ b/common/common.iml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ </component>
+</module> \ No newline at end of file
diff --git a/common/src/com/android/tools/layoutlib/annotations/LayoutlibDelegate.java b/common/src/com/android/tools/layoutlib/annotations/LayoutlibDelegate.java
new file mode 100644
index 0000000000..ca480d7f62
--- /dev/null
+++ b/common/src/com/android/tools/layoutlib/annotations/LayoutlibDelegate.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2017 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.annotations;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Denotes a method that has been converted to a delegate by layoutlib_create.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+public @interface LayoutlibDelegate {
+}
diff --git a/common/src/com/android/tools/layoutlib/annotations/Nullable.java b/common/src/com/android/tools/layoutlib/annotations/Nullable.java
new file mode 100644
index 0000000000..3d91f92087
--- /dev/null
+++ b/common/src/com/android/tools/layoutlib/annotations/Nullable.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2017 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.annotations;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Denotes a parameter or field can be null.
+ * <p/>
+ * When decorating a method call parameter, this denotes the parameter can
+ * legitimately be null and the method will gracefully deal with it. Typically used
+ * on optional parameters.
+ * <p/>
+ * When decorating a method, this denotes the method might legitimately return null.
+ * <p/>
+ * This is a marker annotation and it has no specific attributes.
+ */
+@Retention(RetentionPolicy.SOURCE)
+public @interface Nullable {
+}
diff --git a/common/src/com/android/tools/layoutlib/annotations/VisibleForTesting.java b/common/src/com/android/tools/layoutlib/annotations/VisibleForTesting.java
new file mode 100644
index 0000000000..487860854d
--- /dev/null
+++ b/common/src/com/android/tools/layoutlib/annotations/VisibleForTesting.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2017 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.annotations;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Denotes that the class, method or field has its visibility relaxed so
+ * that unit tests can access it.
+ * <p/>
+ * The <code>visibility</code> argument can be used to specific what the original
+ * visibility should have been if it had not been made public or package-private for testing.
+ * The default is to consider the element private.
+ */
+@Retention(RetentionPolicy.SOURCE)
+public @interface VisibleForTesting {
+ /**
+ * Intended visibility if the element had not been made public or package-private for
+ * testing.
+ */
+ enum Visibility {
+ /** The element should be considered protected. */
+ PROTECTED,
+ /** The element should be considered package-private. */
+ PACKAGE,
+ /** The element should be considered private. */
+ PRIVATE
+ }
+
+ /**
+ * Intended visibility if the element had not been made public or package-private for testing.
+ * If not specified, one should assume the element originally intended to be private.
+ */
+ Visibility visibility() default Visibility.PRIVATE;
+}
diff --git a/create/Android.mk b/create/Android.mk
index 7611cde3f3..0874022105 100644
--- a/create/Android.mk
+++ b/create/Android.mk
@@ -20,7 +20,8 @@ LOCAL_SRC_FILES := $(call all-java-files-under,src)
LOCAL_JAR_MANIFEST := manifest.txt
LOCAL_STATIC_JAVA_LIBRARIES := \
- asm-5.2
+ asm-5.2 \
+ layoutlib-common
LOCAL_MODULE := layoutlib_create
diff --git a/create/create.iml b/create/create.iml
index 237d85bec3..39f232af94 100644
--- a/create/create.iml
+++ b/create/create.iml
@@ -23,5 +23,6 @@
</library>
</orderEntry>
<orderEntry type="library" scope="TEST" name="junit" level="project" />
+ <orderEntry type="module" module-name="common" />
</component>
</module> \ No newline at end of file
diff --git a/create/src/com/android/tools/layoutlib/create/AsmGenerator.java b/create/src/com/android/tools/layoutlib/create/AsmGenerator.java
index d59b419801..395bfb8fa4 100644
--- a/create/src/com/android/tools/layoutlib/create/AsmGenerator.java
+++ b/create/src/com/android/tools/layoutlib/create/AsmGenerator.java
@@ -378,10 +378,6 @@ public class AsmGenerator {
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);
}
diff --git a/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index cb0bc6d3c4..5951a67f6b 100644
--- a/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -133,6 +133,7 @@ public final class CreateInfo implements ICreateInfo {
"android.content.res.Resources#getDimensionPixelSize",
"android.content.res.Resources#getDrawable",
"android.content.res.Resources#getFont",
+ "android.content.res.Resources#getIdentifier",
"android.content.res.Resources#getIntArray",
"android.content.res.Resources#getInteger",
"android.content.res.Resources#getLayout",
diff --git a/create/src/com/android/tools/layoutlib/create/FieldInjectorAdapter.java b/create/src/com/android/tools/layoutlib/create/FieldInjectorAdapter.java
deleted file mode 100644
index 4608a84af3..0000000000
--- a/create/src/com/android/tools/layoutlib/create/FieldInjectorAdapter.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * 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();
- }
-}