Merge "Add properties from textAppearance to property map" into nyc-dev

This commit is contained in:
Deepanshu Gupta
2016-04-05 23:59:00 +00:00
committed by Android (Google) Code Review

View File

@@ -110,13 +110,13 @@ import static com.android.layoutlib.bridge.android.RenderParamsFlags.FLAG_KEY_AP
public final class BridgeContext extends Context { public final class BridgeContext extends Context {
/** The map adds cookies to each view so that IDE can link xml tags to views. */ /** The map adds cookies to each view so that IDE can link xml tags to views. */
private final HashMap<View, Object> mViewKeyMap = new HashMap<View, Object>(); private final HashMap<View, Object> mViewKeyMap = new HashMap<>();
/** /**
* In some cases, when inflating an xml, some objects are created. Then later, the objects are * In some cases, when inflating an xml, some objects are created. Then later, the objects are
* converted to views. This map stores the mapping from objects to cookies which can then be * converted to views. This map stores the mapping from objects to cookies which can then be
* used to populate the mViewKeyMap. * used to populate the mViewKeyMap.
*/ */
private final HashMap<Object, Object> mViewKeyHelpMap = new HashMap<Object, Object>(); private final HashMap<Object, Object> mViewKeyHelpMap = new HashMap<>();
private final BridgeAssetManager mAssets; private final BridgeAssetManager mAssets;
private Resources mSystemResources; private Resources mSystemResources;
private final Object mProjectKey; private final Object mProjectKey;
@@ -132,8 +132,7 @@ public final class BridgeContext extends Context {
private Resources.Theme mTheme; private Resources.Theme mTheme;
private final Map<Object, Map<String, String>> mDefaultPropMaps = private final Map<Object, PropertiesMap> mDefaultPropMaps = new IdentityHashMap<>();
new IdentityHashMap<Object, Map<String,String>>();
// maps for dynamically generated id representing style objects (StyleResourceValue) // maps for dynamically generated id representing style objects (StyleResourceValue)
@Nullable @Nullable
@@ -142,13 +141,12 @@ public final class BridgeContext extends Context {
private int mDynamicIdGenerator = 0x02030000; // Base id for R.style in custom namespace private int mDynamicIdGenerator = 0x02030000; // Base id for R.style in custom namespace
// cache for TypedArray generated from StyleResourceValue object // cache for TypedArray generated from StyleResourceValue object
private Map<int[], Map<List<StyleResourceValue>, Map<Integer, BridgeTypedArray>>> private TypedArrayCache mTypedArrayCache;
mTypedArrayCache;
private BridgeInflater mBridgeInflater; private BridgeInflater mBridgeInflater;
private BridgeContentResolver mContentResolver; private BridgeContentResolver mContentResolver;
private final Stack<BridgeXmlBlockParser> mParserStack = new Stack<BridgeXmlBlockParser>(); private final Stack<BridgeXmlBlockParser> mParserStack = new Stack<>();
private SharedPreferences mSharedPreferences; private SharedPreferences mSharedPreferences;
private ClassLoader mClassLoader; private ClassLoader mClassLoader;
private IBinder mBinder; private IBinder mBinder;
@@ -162,7 +160,7 @@ public final class BridgeContext extends Context {
* This a map from value to attribute name. Warning for missing references shouldn't be logged * This a map from value to attribute name. Warning for missing references shouldn't be logged
* if value and attr name pair is the same as an entry in this map. * if value and attr name pair is the same as an entry in this map.
*/ */
private static Map<String, String> RTL_ATTRS = new HashMap<String, String>(10); private static Map<String, String> RTL_ATTRS = new HashMap<>(10);
static { static {
RTL_ATTRS.put("?android:attr/paddingLeft", "paddingStart"); RTL_ATTRS.put("?android:attr/paddingLeft", "paddingStart");
@@ -325,11 +323,11 @@ public final class BridgeContext extends Context {
return mParserStack.get(mParserStack.size() - 2); return mParserStack.get(mParserStack.size() - 2);
} }
public boolean resolveThemeAttribute(int resid, TypedValue outValue, boolean resolveRefs) { public boolean resolveThemeAttribute(int resId, TypedValue outValue, boolean resolveRefs) {
Pair<ResourceType, String> resourceInfo = Bridge.resolveResourceId(resid); Pair<ResourceType, String> resourceInfo = Bridge.resolveResourceId(resId);
boolean isFrameworkRes = true; boolean isFrameworkRes = true;
if (resourceInfo == null) { if (resourceInfo == null) {
resourceInfo = mLayoutlibCallback.resolveResourceId(resid); resourceInfo = mLayoutlibCallback.resolveResourceId(resId);
isFrameworkRes = false; isFrameworkRes = false;
} }
@@ -602,23 +600,20 @@ public final class BridgeContext extends Context {
@Override @Override
public final BridgeTypedArray obtainStyledAttributes(int[] attrs) { public final BridgeTypedArray obtainStyledAttributes(int[] attrs) {
// No style is specified here, so create the typed array based on the default theme return obtainStyledAttributes(0, attrs);
// and the styles already applied to it. A null value of style indicates that the default
// theme should be used.
return createStyleBasedTypedArray(null, attrs);
} }
@Override @Override
public final BridgeTypedArray obtainStyledAttributes(int resid, int[] attrs) public final BridgeTypedArray obtainStyledAttributes(int resId, int[] attrs)
throws Resources.NotFoundException { throws Resources.NotFoundException {
StyleResourceValue style = null; StyleResourceValue style = null;
// get the StyleResourceValue based on the resId; // get the StyleResourceValue based on the resId;
if (resid != 0) { if (resId != 0) {
style = getStyleByDynamicId(resid); style = getStyleByDynamicId(resId);
if (style == null) { if (style == null) {
// In some cases, style may not be a dynamic id, so we do a full search. // In some cases, style may not be a dynamic id, so we do a full search.
ResourceReference ref = resolveId(resid); ResourceReference ref = resolveId(resId);
if (ref != null) { if (ref != null) {
style = mRenderResources.getStyle(ref.getName(), ref.isFramework()); style = mRenderResources.getStyle(ref.getName(), ref.isFramework());
} }
@@ -629,41 +624,33 @@ public final class BridgeContext extends Context {
} }
} }
// The map is from
// attrs (int[]) -> context's current themes (List<StyleRV>) -> resid (int) -> typed array.
if (mTypedArrayCache == null) { if (mTypedArrayCache == null) {
mTypedArrayCache = new IdentityHashMap<int[], mTypedArrayCache = new TypedArrayCache();
Map<List<StyleResourceValue>, Map<Integer, BridgeTypedArray>>>();
} }
// get the 2nd map
Map<List<StyleResourceValue>, Map<Integer, BridgeTypedArray>> map2 =
mTypedArrayCache.get(attrs);
if (map2 == null) {
map2 = new HashMap<List<StyleResourceValue>, Map<Integer, BridgeTypedArray>>();
mTypedArrayCache.put(attrs, map2);
}
// get the 3rd map
List<StyleResourceValue> currentThemes = mRenderResources.getAllThemes(); List<StyleResourceValue> currentThemes = mRenderResources.getAllThemes();
Map<Integer, BridgeTypedArray> map3 = map2.get(currentThemes);
if (map3 == null) { Pair<BridgeTypedArray, PropertiesMap> typeArrayAndPropertiesPair =
map3 = new HashMap<Integer, BridgeTypedArray>(); mTypedArrayCache.get(attrs, currentThemes, resId);
// Create a copy of the list before adding it to the map. This allows reusing the
// existing list. if (typeArrayAndPropertiesPair == null) {
currentThemes = new ArrayList<StyleResourceValue>(currentThemes); typeArrayAndPropertiesPair = createStyleBasedTypedArray(style, attrs);
map2.put(currentThemes, map3); mTypedArrayCache.put(attrs, currentThemes, resId, typeArrayAndPropertiesPair);
} }
// Add value to defaultPropsMap if needed
// get the array from the 3rd map if (typeArrayAndPropertiesPair.getSecond() != null) {
BridgeTypedArray ta = map3.get(resid); Object key = getCurrentParser().getViewCookie();
if (key != null) {
if (ta == null) { PropertiesMap defaultPropMap = mDefaultPropMaps.get(key);
ta = createStyleBasedTypedArray(style, attrs); if (defaultPropMap == null) {
map3.put(resid, ta); defaultPropMap = typeArrayAndPropertiesPair.getSecond();
mDefaultPropMaps.put(key, defaultPropMap);
} else {
defaultPropMap.putAll(typeArrayAndPropertiesPair.getSecond());
}
}
} }
return typeArrayAndPropertiesPair.getFirst();
return ta;
} }
@Override @Override
@@ -675,7 +662,7 @@ public final class BridgeContext extends Context {
public BridgeTypedArray obtainStyledAttributes(AttributeSet set, int[] attrs, public BridgeTypedArray obtainStyledAttributes(AttributeSet set, int[] attrs,
int defStyleAttr, int defStyleRes) { int defStyleAttr, int defStyleRes) {
Map<String, String> defaultPropMap = null; PropertiesMap defaultPropMap = null;
boolean isPlatformFile = true; boolean isPlatformFile = true;
// Hint: for XmlPullParser, attach source //DEVICE_SRC/dalvik/libcore/xml/src/java // Hint: for XmlPullParser, attach source //DEVICE_SRC/dalvik/libcore/xml/src/java
@@ -689,7 +676,7 @@ public final class BridgeContext extends Context {
if (key != null) { if (key != null) {
defaultPropMap = mDefaultPropMaps.get(key); defaultPropMap = mDefaultPropMaps.get(key);
if (defaultPropMap == null) { if (defaultPropMap == null) {
defaultPropMap = new HashMap<String, String>(); defaultPropMap = new PropertiesMap();
mDefaultPropMaps.put(key, defaultPropMap); mDefaultPropMaps.put(key, defaultPropMap);
} }
} }
@@ -937,32 +924,33 @@ public final class BridgeContext extends Context {
* *
* @see #obtainStyledAttributes(int, int[]) * @see #obtainStyledAttributes(int, int[])
*/ */
private BridgeTypedArray createStyleBasedTypedArray(@Nullable StyleResourceValue style, private Pair<BridgeTypedArray, PropertiesMap> createStyleBasedTypedArray(
int[] attrs) throws Resources.NotFoundException { @Nullable StyleResourceValue style, int[] attrs) throws Resources.NotFoundException {
List<Pair<String, Boolean>> attributes = searchAttrs(attrs); List<Pair<String, Boolean>> attributes = searchAttrs(attrs);
BridgeTypedArray ta = Resources_Delegate.newTypeArray(mSystemResources, attrs.length, BridgeTypedArray ta = Resources_Delegate.newTypeArray(mSystemResources, attrs.length, false);
false);
PropertiesMap defaultPropMap = new PropertiesMap();
// for each attribute, get its name so that we can search it in the style // for each attribute, get its name so that we can search it in the style
for (int i = 0 ; i < attrs.length ; i++) { for (int i = 0; i < attrs.length; i++) {
Pair<String, Boolean> attribute = attributes.get(i); Pair<String, Boolean> attribute = attributes.get(i);
if (attribute != null) { if (attribute != null) {
// look for the value in the given style // look for the value in the given style
ResourceValue resValue; ResourceValue resValue;
String attrName = attribute.getFirst();
if (style != null) { if (style != null) {
resValue = mRenderResources.findItemInStyle(style, attribute.getFirst(), resValue = mRenderResources.findItemInStyle(style, attrName,
attribute.getSecond()); attribute.getSecond());
} else { } else {
resValue = mRenderResources.findItemInTheme(attribute.getFirst(), resValue = mRenderResources.findItemInTheme(attrName, attribute.getSecond());
attribute.getSecond());
} }
if (resValue != null) { if (resValue != null) {
// Add it to defaultPropMap before resolving
defaultPropMap.put(attrName, resValue.getValue());
// resolve it to make sure there are no references left. // resolve it to make sure there are no references left.
ta.bridgeSetValue(i, attribute.getFirst(), attribute.getSecond(), ta.bridgeSetValue(i, attrName, attribute.getSecond(),
mRenderResources.resolveResValue(resValue)); mRenderResources.resolveResValue(resValue));
} }
} }
@@ -970,7 +958,7 @@ public final class BridgeContext extends Context {
ta.sealArray(); ta.sealArray();
return ta; return Pair.of(ta, defaultPropMap);
} }
/** /**
@@ -982,7 +970,7 @@ public final class BridgeContext extends Context {
* @return List of attribute information. * @return List of attribute information.
*/ */
private List<Pair<String, Boolean>> searchAttrs(int[] attrs) { private List<Pair<String, Boolean>> searchAttrs(int[] attrs) {
List<Pair<String, Boolean>> results = new ArrayList<Pair<String, Boolean>>(attrs.length); List<Pair<String, Boolean>> results = new ArrayList<>(attrs.length);
// for each attribute, get its name so that we can search it in the style // for each attribute, get its name so that we can search it in the style
for (int attr : attrs) { for (int attr : attrs) {
@@ -1011,7 +999,7 @@ public final class BridgeContext extends Context {
* @return A (name, isFramework) pair describing the attribute if found. Returns null * @return A (name, isFramework) pair describing the attribute if found. Returns null
* if nothing is found. * if nothing is found.
*/ */
public Pair<String, Boolean> searchAttr(int attr) { private Pair<String, Boolean> searchAttr(int attr) {
Pair<ResourceType, String> info = Bridge.resolveResourceId(attr); Pair<ResourceType, String> info = Bridge.resolveResourceId(attr);
if (info != null) { if (info != null) {
return Pair.of(info.getSecond(), Boolean.TRUE); return Pair.of(info.getSecond(), Boolean.TRUE);
@@ -1028,8 +1016,8 @@ public final class BridgeContext extends Context {
public int getDynamicIdByStyle(StyleResourceValue resValue) { public int getDynamicIdByStyle(StyleResourceValue resValue) {
if (mDynamicIdToStyleMap == null) { if (mDynamicIdToStyleMap == null) {
// create the maps. // create the maps.
mDynamicIdToStyleMap = new HashMap<Integer, StyleResourceValue>(); mDynamicIdToStyleMap = new HashMap<>();
mStyleToDynamicIdMap = new HashMap<StyleResourceValue, Integer>(); mStyleToDynamicIdMap = new HashMap<>();
} }
// look for an existing id // look for an existing id
@@ -1868,4 +1856,69 @@ public final class BridgeContext extends Context {
public boolean isCredentialProtectedStorage() { public boolean isCredentialProtectedStorage() {
return false; return false;
} }
/**
* The cached value depends on
* <ol>
* <li>{@code int[]}: the attributes for which TypedArray is created </li>
* <li>{@code List<StyleResourceValue>}: the themes set on the context at the time of
* creation of the TypedArray</li>
* <li>{@code Integer}: the default style used at the time of creation</li>
* </ol>
*
* The class is created by using nested maps resolving one dependency at a time.
* <p/>
* The final value of the nested maps is a pair of the typed array and a map of properties
* that should be added to {@link #mDefaultPropMaps}, if needed.
*/
private static class TypedArrayCache {
private Map<int[],
Map<List<StyleResourceValue>,
Map<Integer, Pair<BridgeTypedArray, PropertiesMap>>>> mCache;
public TypedArrayCache() {
mCache = new IdentityHashMap<>();
}
public Pair<BridgeTypedArray, PropertiesMap> get(int[] attrs,
List<StyleResourceValue> themes, int resId) {
Map<List<StyleResourceValue>, Map<Integer, Pair<BridgeTypedArray, PropertiesMap>>>
cacheFromThemes = mCache.get(attrs);
if (cacheFromThemes != null) {
Map<Integer, Pair<BridgeTypedArray, PropertiesMap>> cacheFromResId =
cacheFromThemes.get(themes);
if (cacheFromResId != null) {
return cacheFromResId.get(resId);
}
}
return null;
}
public void put(int[] attrs, List<StyleResourceValue> themes, int resId,
Pair<BridgeTypedArray, PropertiesMap> value) {
Map<List<StyleResourceValue>, Map<Integer, Pair<BridgeTypedArray, PropertiesMap>>>
cacheFromThemes = mCache.get(attrs);
if (cacheFromThemes == null) {
cacheFromThemes = new HashMap<>();
mCache.put(attrs, cacheFromThemes);
}
Map<Integer, Pair<BridgeTypedArray, PropertiesMap>> cacheFromResId =
cacheFromThemes.get(themes);
if (cacheFromResId == null) {
cacheFromResId = new HashMap<>();
cacheFromThemes.put(themes, cacheFromResId);
}
cacheFromResId.put(resId, value);
}
}
/**
* An alias used for the value in {@code {@link #mDefaultPropMaps}}
*/
private static class PropertiesMap extends HashMap<String, String> {
}
} }