use of org.robolectric.res.android.ResourceTypes.Res_value in project robolectric by robolectric.
the class AttributeSetBuilderImpl method build.
@Override
public AttributeSet build() {
Class<?> xmlBlockClass = ReflectionHelpers.loadClass(this.getClass().getClassLoader(), "android.content.res.XmlBlock");
ByteBuffer buf = ByteBuffer.allocate(16 * 1024).order(ByteOrder.LITTLE_ENDIAN);
Writer resStringPoolWriter = new Writer();
final SparseArray<Integer> resIds = new SparseArray<>();
final int[] maxAttrNameIndex = new int[] { 0 };
ResXMLTree_attrExt.Writer dummyStart = new ResXMLTree_attrExt.Writer(buf, resStringPoolWriter, null, "dummy") {
{
String packageName = resourceResolver.getPackageName();
for (Entry<Integer, String> entry : attrToValue.entrySet()) {
Integer attrId = entry.getKey();
String attrNs = "";
String attrName;
ResName attrResName = null;
String magicAttr = MAGIC_ATTRS.get(attrId);
if (magicAttr != null) {
attrId = null;
attrName = magicAttr;
} else {
String attrNameStr = resourceResolver.getResourceName(attrId);
attrResName = ResName.qualifyResName(attrNameStr, packageName, "attr");
attrNs = attrResName.packageName.equals("android") ? ANDROID_NS : AUTO_NS;
attrName = attrResName.name;
}
String value = entry.getValue();
DataType type;
int valueInt;
if (value == null || AttributeResource.isNull(value)) {
type = DataType.NULL;
valueInt = TypedValue.DATA_NULL_EMPTY;
} else if (AttributeResource.isResourceReference(value)) {
ResName resRef = AttributeResource.getResourceReference(value, packageName, null);
Integer valueResId = resourceResolver.getIdentifier(resRef.name, resRef.type, resRef.packageName);
if (valueResId == 0) {
throw new IllegalArgumentException("no such resource " + value + " while resolving value for " + (attrResName == null ? attrName : attrResName.getFullyQualifiedName()));
}
type = DataType.REFERENCE;
if (attrResName != null) {
value = "@" + valueResId;
}
valueInt = valueResId;
} else if (AttributeResource.isStyleReference(value)) {
ResName resRef = AttributeResource.getStyleReference(value, packageName, "attr");
Integer valueResId = resourceResolver.getIdentifier(resRef.name, resRef.type, resRef.packageName);
if (valueResId == 0) {
throw new IllegalArgumentException("no such attr " + value + " while resolving value for " + (attrResName == null ? attrName : attrResName.getFullyQualifiedName()));
}
type = DataType.ATTRIBUTE;
valueInt = valueResId;
} else if (attrResName == null) {
// class, id, or style
type = DataType.STRING;
valueInt = resStringPoolWriter.string(value);
} else {
TypedValue outValue = parse(attrId, attrResName, value, packageName);
type = DataType.fromCode(outValue.type);
value = (String) outValue.string;
if (type == DataType.STRING && outValue.data == 0) {
valueInt = resStringPoolWriter.string(value);
} else {
valueInt = outValue.data;
}
}
Res_value resValue = new Res_value(type.code(), valueInt);
int attrNameIndex = resStringPoolWriter.uniqueString(attrName);
attr(resStringPoolWriter.string(attrNs), attrNameIndex, resStringPoolWriter.string(value), resValue, attrNs + ":" + attrName);
if (attrId != null) {
resIds.put(attrNameIndex, attrId);
}
maxAttrNameIndex[0] = Math.max(maxAttrNameIndex[0], attrNameIndex);
}
}
};
ResXMLTree_endElementExt.Writer dummyEnd = new ResXMLTree_endElementExt.Writer(buf, resStringPoolWriter, null, "dummy");
int finalMaxAttrNameIndex = maxAttrNameIndex[0];
ResXMLTree_header.write(buf, resStringPoolWriter, () -> {
if (finalMaxAttrNameIndex > 0) {
ResChunk_header.write(buf, (short) RES_XML_RESOURCE_MAP_TYPE, () -> {
}, () -> {
// not particularly compact, but no big deal for our purposes...
for (int i = 0; i <= finalMaxAttrNameIndex; i++) {
Integer value = resIds.get(i);
buf.putInt(value == null ? 0 : value);
}
});
}
ResXMLTree_node.write(buf, RES_XML_START_ELEMENT_TYPE, dummyStart::write);
ResXMLTree_node.write(buf, RES_XML_END_ELEMENT_TYPE, dummyEnd::write);
});
int size = buf.position();
byte[] bytes = new byte[size];
// Cast to Buffer because generated covariant return type that returns ByteBuffer is not
// available on Java 8
((Buffer) buf).position(0);
buf.get(bytes, 0, size);
Object xmlBlockInstance = ReflectionHelpers.callConstructor(xmlBlockClass, ClassParameter.from(byte[].class, bytes));
AttributeSet parser = ReflectionHelpers.callInstanceMethod(xmlBlockClass, xmlBlockInstance, "newParser");
ReflectionHelpers.callInstanceMethod(parser, "next");
ReflectionHelpers.callInstanceMethod(parser, "next");
return parser;
}
use of org.robolectric.res.android.ResourceTypes.Res_value in project robolectric by robolectric.
the class ShadowXmlBlock method nativeGetStyleAttribute.
@Implementation(minSdk = VERSION_CODES.LOLLIPOP)
protected static int nativeGetStyleAttribute(long state) {
ResXMLParser resXMLParser = getResXMLParser(state);
int idx = resXMLParser.indexOfStyle();
if (idx < 0) {
return 0;
}
final Ref<Res_value> valueRef = new Ref<>(new Res_value());
if (resXMLParser.getAttributeValue(idx, valueRef) < 0) {
return 0;
}
Res_value value = valueRef.get();
return value.dataType == org.robolectric.res.android.ResourceTypes.Res_value.TYPE_REFERENCE || value.dataType == org.robolectric.res.android.ResourceTypes.Res_value.TYPE_ATTRIBUTE ? value.data : 0;
}
use of org.robolectric.res.android.ResourceTypes.Res_value in project robolectric by robolectric.
the class AttributeResolution method ResolveAttrs.
public static boolean ResolveAttrs(ResTableTheme theme, int defStyleAttr, int defStyleRes, int[] srcValues, int srcValuesLength, int[] attrs, int attrsLength, int[] outValues, int[] outIndices) {
if (kDebugStyles) {
ALOGI("APPLY STYLE: theme=0x%p defStyleAttr=0x%x defStyleRes=0x%x", theme, defStyleAttr, defStyleRes);
}
final ResTable res = theme.getResTable();
ResTable_config config = new ResTable_config();
Res_value value;
int indicesIdx = 0;
// Load default style from attribute, if specified...
Ref<Integer> defStyleBagTypeSetFlags = new Ref<>(0);
if (defStyleAttr != 0) {
Ref<Res_value> valueRef = new Ref<>(null);
if (theme.GetAttribute(defStyleAttr, valueRef, defStyleBagTypeSetFlags) >= 0) {
value = valueRef.get();
if (value.dataType == Res_value.TYPE_REFERENCE) {
defStyleRes = value.data;
}
}
}
// Now lock down the resource object and start pulling stuff from it.
res.lock();
// Retrieve the default style bag, if requested.
final Ref<ResTable.bag_entry[]> defStyleStart = new Ref<>(null);
Ref<Integer> defStyleTypeSetFlags = new Ref<>(0);
int bagOff = defStyleRes != 0 ? res.getBagLocked(defStyleRes, defStyleStart, defStyleTypeSetFlags) : -1;
defStyleTypeSetFlags.set(defStyleTypeSetFlags.get() | defStyleBagTypeSetFlags.get());
// const ResTable::bag_entry* const defStyleEnd = defStyleStart + (bagOff >= 0 ? bagOff : 0);
final int defStyleEnd = (bagOff >= 0 ? bagOff : 0);
BagAttributeFinder defStyleAttrFinder = new BagAttributeFinder(defStyleStart.get(), defStyleEnd);
// Now iterate through all of the attributes that the client has requested,
// filling in each with whatever data we can find.
int destOffset = 0;
for (int ii = 0; ii < attrsLength; ii++) {
final int curIdent = attrs[ii];
if (kDebugStyles) {
ALOGI("RETRIEVING ATTR 0x%08x...", curIdent);
}
int block = -1;
int typeSetFlags = 0;
value = Res_value.NULL_VALUE;
config.density = 0;
// Retrieve the current input value if available.
if (srcValuesLength > 0 && srcValues[ii] != 0) {
value = new Res_value((byte) Res_value.TYPE_ATTRIBUTE, srcValues[ii]);
if (kDebugStyles) {
ALOGI("-> From values: type=0x%x, data=0x%08x", value.dataType, value.data);
}
} else {
final ResTable.bag_entry defStyleEntry = defStyleAttrFinder.find(curIdent);
if (defStyleEntry != null) {
block = defStyleEntry.stringBlock;
typeSetFlags = defStyleTypeSetFlags.get();
value = defStyleEntry.map.value;
if (kDebugStyles) {
ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
}
}
}
int resid = 0;
Ref<Res_value> valueRef = new Ref<>(value);
Ref<Integer> residRef = new Ref<>(resid);
Ref<Integer> typeSetFlagsRef = new Ref<>(typeSetFlags);
Ref<ResTable_config> configRef = new Ref<>(config);
if (value.dataType != Res_value.TYPE_NULL) {
// Take care of resolving the found resource to its final value.
int newBlock = theme.resolveAttributeReference(valueRef, block, residRef, typeSetFlagsRef, configRef);
value = valueRef.get();
resid = residRef.get();
typeSetFlags = typeSetFlagsRef.get();
config = configRef.get();
if (newBlock >= 0)
block = newBlock;
if (kDebugStyles) {
ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
}
} else {
// If we still don't have a value for this attribute, try to find
// it in the theme!
int newBlock = theme.GetAttribute(curIdent, valueRef, typeSetFlagsRef);
value = valueRef.get();
typeSetFlags = typeSetFlagsRef.get();
if (newBlock >= 0) {
if (kDebugStyles) {
ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
}
newBlock = res.resolveReference(valueRef, newBlock, residRef, typeSetFlagsRef, configRef);
value = valueRef.get();
resid = residRef.get();
typeSetFlags = typeSetFlagsRef.get();
config = configRef.get();
if (kThrowOnBadId) {
if (newBlock == BAD_INDEX) {
throw new IllegalStateException("Bad resource!");
}
}
if (newBlock >= 0)
block = newBlock;
if (kDebugStyles) {
ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
}
}
}
// Deal with the special @null value -- it turns back to TYPE_NULL.
if (value.dataType == Res_value.TYPE_REFERENCE && value.data == 0) {
if (kDebugStyles) {
ALOGI("-> Setting to @null!");
}
value = Res_value.NULL_VALUE;
block = -1;
}
if (kDebugStyles) {
ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", curIdent, value.dataType, value.data);
}
// Write the final value back to Java.
outValues[destOffset + STYLE_TYPE] = value.dataType;
outValues[destOffset + STYLE_DATA] = value.data;
outValues[destOffset + STYLE_ASSET_COOKIE] = block != -1 ? res.getTableCookie(block) : -1;
outValues[destOffset + STYLE_RESOURCE_ID] = resid;
outValues[destOffset + STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
outValues[destOffset + STYLE_DENSITY] = config.density;
if (outIndices != null && value.dataType != Res_value.TYPE_NULL) {
indicesIdx++;
outIndices[indicesIdx] = ii;
}
destOffset += STYLE_NUM_ENTRIES;
}
res.unlock();
if (outIndices != null) {
outIndices[0] = indicesIdx;
}
return true;
}
use of org.robolectric.res.android.ResourceTypes.Res_value in project robolectric by robolectric.
the class AttributeResolution method ApplyStyle.
public static void ApplyStyle(ResTableTheme theme, ResXMLParser xmlParser, int defStyleAttr, int defStyleRes, int[] attrs, int attrsLength, int[] outValues, int[] outIndices) {
if (kDebugStyles) {
ALOGI("APPLY STYLE: theme=%s defStyleAttr=0x%x defStyleRes=0x%x xml=%s", theme, defStyleAttr, defStyleRes, xmlParser);
}
final ResTable res = theme.getResTable();
Ref<ResTable_config> config = new Ref<>(new ResTable_config());
Ref<Res_value> value = new Ref<>(new Res_value());
int indices_idx = 0;
// Load default style from attribute, if specified...
Ref<Integer> defStyleBagTypeSetFlags = new Ref<>(0);
if (defStyleAttr != 0) {
if (theme.GetAttribute(defStyleAttr, value, defStyleBagTypeSetFlags) >= 0) {
if (value.get().dataType == DataType.REFERENCE.code()) {
defStyleRes = value.get().data;
}
}
}
// Retrieve the style class associated with the current XML tag.
int style = 0;
Ref<Integer> styleBagTypeSetFlags = new Ref<>(0);
if (xmlParser != null) {
int idx = xmlParser.indexOfStyle();
if (idx >= 0 && xmlParser.getAttributeValue(idx, value) >= 0) {
if (value.get().dataType == DataType.ATTRIBUTE.code()) {
if (theme.GetAttribute(value.get().data, value, styleBagTypeSetFlags) < 0) {
value.set(value.get().withType(DataType.NULL.code()));
}
}
if (value.get().dataType == DataType.REFERENCE.code()) {
style = value.get().data;
}
}
}
// Now lock down the resource object and start pulling stuff from it.
res.lock();
// Retrieve the default style bag, if requested.
final Ref<ResTable.bag_entry[]> defStyleAttrStart = new Ref<>(null);
Ref<Integer> defStyleTypeSetFlags = new Ref<>(0);
int bagOff = defStyleRes != 0 ? res.getBagLocked(defStyleRes, defStyleAttrStart, defStyleTypeSetFlags) : -1;
defStyleTypeSetFlags.set(defStyleTypeSetFlags.get() | defStyleBagTypeSetFlags.get());
// const ResTable::bag_entry* defStyleAttrEnd = defStyleAttrStart + (bagOff >= 0 ? bagOff : 0);
final ResTable.bag_entry defStyleAttrEnd = null;
// BagAttributeFinder defStyleAttrFinder = new BagAttributeFinder(defStyleAttrStart, defStyleAttrEnd);
BagAttributeFinder defStyleAttrFinder = new BagAttributeFinder(defStyleAttrStart.get(), bagOff);
// Retrieve the style class bag, if requested.
final Ref<ResTable.bag_entry[]> styleAttrStart = new Ref<>(null);
Ref<Integer> styleTypeSetFlags = new Ref<>(0);
bagOff = style != 0 ? res.getBagLocked(style, styleAttrStart, styleTypeSetFlags) : -1;
styleTypeSetFlags.set(styleTypeSetFlags.get() | styleBagTypeSetFlags.get());
// final ResTable::bag_entry* final styleAttrEnd = styleAttrStart + (bagOff >= 0 ? bagOff : 0);
final ResTable.bag_entry styleAttrEnd = null;
// BagAttributeFinder styleAttrFinder = new BagAttributeFinder(styleAttrStart, styleAttrEnd);
BagAttributeFinder styleAttrFinder = new BagAttributeFinder(styleAttrStart.get(), bagOff);
// Retrieve the XML attributes, if requested.
final int kXmlBlock = 0x10000000;
XmlAttributeFinder xmlAttrFinder = new XmlAttributeFinder(xmlParser);
final int xmlAttrEnd = xmlParser != null ? xmlParser.getAttributeCount() : 0;
// filling in each with whatever data we can find.
for (int ii = 0; ii < attrsLength; ii++) {
final int curIdent = attrs[ii];
if (kDebugStyles) {
ALOGI("RETRIEVING ATTR 0x%08x...", curIdent);
}
int block = kXmlBlock;
Ref<Integer> typeSetFlags = new Ref<>(0);
value.set(Res_value.NULL_VALUE);
config.get().density = 0;
// Try to find a value for this attribute... we prioritize values
// coming from, first XML attributes, then XML style, then default
// style, and finally the theme.
// Walk through the xml attributes looking for the requested attribute.
final int xmlAttrIdx = xmlAttrFinder.find(curIdent);
if (xmlAttrIdx != xmlAttrEnd) {
// We found the attribute we were looking for.
xmlParser.getAttributeValue(xmlAttrIdx, value);
if (kDebugStyles) {
ALOGI("-> From XML: type=0x%x, data=0x%08x", value.get().dataType, value.get().data);
}
}
if (value.get().dataType == DataType.NULL.code() && value.get().data != Res_value.DATA_NULL_EMPTY) {
// Walk through the style class values looking for the requested attribute.
final ResTable.bag_entry styleAttrEntry = styleAttrFinder.find(curIdent);
if (styleAttrEntry != styleAttrEnd) {
// We found the attribute we were looking for.
block = styleAttrEntry.stringBlock;
typeSetFlags.set(styleTypeSetFlags.get());
value.set(styleAttrEntry.map.value);
if (kDebugStyles) {
ALOGI("-> From style: type=0x%x, data=0x%08x", value.get().dataType, value.get().data);
}
}
}
if (value.get().dataType == DataType.NULL.code() && value.get().data != Res_value.DATA_NULL_EMPTY) {
// Walk through the default style values looking for the requested attribute.
final ResTable.bag_entry defStyleAttrEntry = defStyleAttrFinder.find(curIdent);
if (defStyleAttrEntry != defStyleAttrEnd) {
// We found the attribute we were looking for.
block = defStyleAttrEntry.stringBlock;
typeSetFlags.set(styleTypeSetFlags.get());
value.set(defStyleAttrEntry.map.value);
if (kDebugStyles) {
ALOGI("-> From def style: type=0x%x, data=0x%08x", value.get().dataType, value.get().data);
}
}
}
Ref<Integer> resid = new Ref<>(0);
if (value.get().dataType != DataType.NULL.code()) {
// Take care of resolving the found resource to its final value.
int newBlock = theme.resolveAttributeReference(value, block, resid, typeSetFlags, config);
if (newBlock >= 0) {
block = newBlock;
}
if (kDebugStyles) {
ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.get().dataType, value.get().data);
}
} else if (value.get().data != Res_value.DATA_NULL_EMPTY) {
// If we still don't have a value for this attribute, try to find it in the theme!
int newBlock = theme.GetAttribute(curIdent, value, typeSetFlags);
if (newBlock >= 0) {
if (kDebugStyles) {
ALOGI("-> From theme: type=0x%x, data=0x%08x", value.get().dataType, value.get().data);
}
newBlock = res.resolveReference(value, newBlock, resid, typeSetFlags, config);
if (newBlock >= 0) {
block = newBlock;
}
if (kDebugStyles) {
ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.get().dataType, value.get().data);
}
}
}
// Deal with the special @null value -- it turns back to TYPE_NULL.
if (value.get().dataType == DataType.REFERENCE.code() && value.get().data == 0) {
if (kDebugStyles) {
ALOGI(". Setting to @null!");
}
value.set(Res_value.NULL_VALUE);
block = kXmlBlock;
}
if (kDebugStyles) {
ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", curIdent, value.get().dataType, value.get().data);
}
// Write the final value back to Java.
int destIndex = ii * STYLE_NUM_ENTRIES;
Res_value res_value = value.get();
outValues[destIndex + STYLE_TYPE] = res_value.dataType;
outValues[destIndex + STYLE_DATA] = res_value.data;
outValues[destIndex + STYLE_ASSET_COOKIE] = block != kXmlBlock ? res.getTableCookie(block) : -1;
outValues[destIndex + STYLE_RESOURCE_ID] = resid.get();
outValues[destIndex + STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags.get();
outValues[destIndex + STYLE_DENSITY] = config.get().density;
if (res_value.dataType != DataType.NULL.code() || res_value.data == Res_value.DATA_NULL_EMPTY) {
indices_idx++;
// out_indices must NOT be nullptr.
outIndices[indices_idx] = ii;
}
if (res_value.dataType == DataType.ATTRIBUTE.code()) {
ResTable.ResourceName attrName = new ResTable.ResourceName();
ResTable.ResourceName attrRefName = new ResTable.ResourceName();
boolean gotName = res.getResourceName(curIdent, true, attrName);
boolean gotRefName = res.getResourceName(res_value.data, true, attrRefName);
Logger.warn("Failed to resolve attribute lookup: %s=\"?%s\"; theme: %s", gotName ? attrName : "unknown", gotRefName ? attrRefName : "unknown", theme);
}
// out_values += STYLE_NUM_ENTRIES;
}
res.unlock();
// out_indices must NOT be nullptr.
outIndices[0] = indices_idx;
}
use of org.robolectric.res.android.ResourceTypes.Res_value in project robolectric by robolectric.
the class AttributeResolution9 method ApplyStyle.
public static void ApplyStyle(Theme theme, ResXMLParser xml_parser, int def_style_attr, int def_style_resid, int[] attrs, int attrs_length, int[] out_values, int[] out_indices) {
if (kDebugStyles) {
ALOGI("APPLY STYLE: theme=%s defStyleAttr=0x%x defStyleRes=0x%x xml=%s", theme, def_style_attr, def_style_resid, xml_parser);
}
CppAssetManager2 assetmanager = theme.GetAssetManager();
final Ref<ResTable_config> config = new Ref<>(new ResTable_config());
final Ref<Res_value> value = new Ref<>(new Res_value());
int indices_idx = 0;
// Load default style from attribute, if specified...
final Ref<Integer> def_style_flags = new Ref<>(0);
if (def_style_attr != 0) {
if (theme.GetAttribute(def_style_attr, value, def_style_flags).intValue() != kInvalidCookie) {
if (value.get().dataType == DataType.REFERENCE.code()) {
def_style_resid = value.get().data;
}
}
}
// Retrieve the style resource ID associated with the current XML tag's style attribute.
int style_resid = 0;
final Ref<Integer> style_flags = new Ref<>(0);
if (xml_parser != null) {
int idx = xml_parser.indexOfStyle();
if (idx >= 0 && xml_parser.getAttributeValue(idx, value) >= 0) {
if (value.get().dataType == DataType.ATTRIBUTE.code()) {
// Resolve the attribute with out theme.
if (theme.GetAttribute(value.get().data, value, style_flags).intValue() == kInvalidCookie) {
value.set(value.get().withType(DataType.NULL.code()));
}
}
if (value.get().dataType == DataType.REFERENCE.code()) {
style_resid = value.get().data;
}
}
}
// Retrieve the default style bag, if requested.
ResolvedBag default_style_bag = null;
if (def_style_resid != 0) {
default_style_bag = assetmanager.GetBag(def_style_resid);
if (default_style_bag != null) {
def_style_flags.set(def_style_flags.get() | default_style_bag.type_spec_flags);
}
}
BagAttributeFinder def_style_attr_finder = new BagAttributeFinder(default_style_bag);
// Retrieve the style class bag, if requested.
ResolvedBag xml_style_bag = null;
if (style_resid != 0) {
xml_style_bag = assetmanager.GetBag(style_resid);
if (xml_style_bag != null) {
style_flags.set(style_flags.get() | xml_style_bag.type_spec_flags);
}
}
BagAttributeFinder xml_style_attr_finder = new BagAttributeFinder(xml_style_bag);
// Retrieve the XML attributes, if requested.
XmlAttributeFinder xml_attr_finder = new XmlAttributeFinder(xml_parser);
// filling in each with whatever data we can find.
for (int ii = 0; ii < attrs_length; ii++) {
final int cur_ident = attrs[ii];
if (kDebugStyles) {
ALOGI("RETRIEVING ATTR 0x%08x...", cur_ident);
}
ApkAssetsCookie cookie = K_INVALID_COOKIE;
final Ref<Integer> type_set_flags = new Ref<>(0);
value.set(Res_value.NULL_VALUE);
config.get().density = 0;
// Try to find a value for this attribute... we prioritize values
// coming from, first XML attributes, then XML style, then default
// style, and finally the theme.
// Walk through the xml attributes looking for the requested attribute.
int xml_attr_idx = xml_attr_finder.Find(cur_ident);
if (xml_attr_idx != -1) {
// We found the attribute we were looking for.
xml_parser.getAttributeValue(xml_attr_idx, value);
type_set_flags.set(style_flags.get());
if (kDebugStyles) {
ALOGI("-> From XML: type=0x%x, data=0x%08x", value.get().dataType, value.get().data);
}
}
if (value.get().dataType == DataType.NULL.code() && value.get().data != Res_value.DATA_NULL_EMPTY) {
// Walk through the style class values looking for the requested attribute.
Entry entry = xml_style_attr_finder.Find(cur_ident);
if (entry != null) {
// We found the attribute we were looking for.
cookie = entry.cookie;
type_set_flags.set(style_flags.get());
value.set(entry.value);
if (kDebugStyles) {
ALOGI("-> From style: type=0x%x, data=0x%08x", value.get().dataType, value.get().data);
}
}
}
if (value.get().dataType == DataType.NULL.code() && value.get().data != Res_value.DATA_NULL_EMPTY) {
// Walk through the default style values looking for the requested attribute.
Entry entry = def_style_attr_finder.Find(cur_ident);
if (entry != null) {
// We found the attribute we were looking for.
cookie = entry.cookie;
type_set_flags.set(def_style_flags.get());
value.set(entry.value);
if (kDebugStyles) {
ALOGI("-> From def style: type=0x%x, data=0x%08x", value.get().dataType, value.get().data);
}
}
}
final Ref<Integer> resid = new Ref<>(0);
if (value.get().dataType != DataType.NULL.code()) {
// Take care of resolving the found resource to its final value.
ApkAssetsCookie new_cookie = theme.ResolveAttributeReference(cookie, value, config, type_set_flags, resid);
if (new_cookie.intValue() != kInvalidCookie) {
cookie = new_cookie;
}
if (kDebugStyles) {
ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.get().dataType, value.get().data);
}
} else if (value.get().data != Res_value.DATA_NULL_EMPTY) {
// If we still don't have a value for this attribute, try to find it in the theme!
ApkAssetsCookie new_cookie = theme.GetAttribute(cur_ident, value, type_set_flags);
if (new_cookie.intValue() != kInvalidCookie) {
if (kDebugStyles) {
ALOGI("-> From theme: type=0x%x, data=0x%08x", value.get().dataType, value.get().data);
}
new_cookie = assetmanager.ResolveReference(new_cookie, value, config, type_set_flags, resid);
if (new_cookie.intValue() != kInvalidCookie) {
cookie = new_cookie;
}
if (kDebugStyles) {
ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.get().dataType, value.get().data);
}
}
}
// Deal with the special @null value -- it turns back to TYPE_NULL.
if (value.get().dataType == DataType.REFERENCE.code() && value.get().data == 0) {
if (kDebugStyles) {
ALOGI(". Setting to @null!");
}
value.set(Res_value.NULL_VALUE);
cookie = K_INVALID_COOKIE;
}
if (kDebugStyles) {
ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", cur_ident, value.get().dataType, value.get().data);
}
// Write the final value back to Java.
int destIndex = ii * STYLE_NUM_ENTRIES;
Res_value res_value = value.get();
out_values[destIndex + STYLE_TYPE] = res_value.dataType;
out_values[destIndex + STYLE_DATA] = res_value.data;
out_values[destIndex + STYLE_ASSET_COOKIE] = ApkAssetsCookieToJavaCookie(cookie);
out_values[destIndex + STYLE_RESOURCE_ID] = resid.get();
out_values[destIndex + STYLE_CHANGING_CONFIGURATIONS] = type_set_flags.get();
out_values[destIndex + STYLE_DENSITY] = config.get().density;
if (res_value.dataType != DataType.NULL.code() || res_value.data == Res_value.DATA_NULL_EMPTY) {
indices_idx++;
// out_indices must NOT be nullptr.
out_indices[indices_idx] = ii;
}
// Robolectric-custom:
// if (false && res_value.dataType == DataType.ATTRIBUTE.code()) {
// final Ref<ResourceName> attrName = new Ref<>(null);
// final Ref<ResourceName> attrRefName = new Ref<>(null);
// boolean gotName = assetmanager.GetResourceName(cur_ident, attrName);
// boolean gotRefName = assetmanager.GetResourceName(res_value.data, attrRefName);
// Logger.warn(
// "Failed to resolve attribute lookup: %s=\"?%s\"; theme: %s",
// gotName ? attrName.get() : "unknown", gotRefName ? attrRefName.get() : "unknown",
// theme);
// }
// out_values += STYLE_NUM_ENTRIES;
}
// out_indices must NOT be nullptr.
out_indices[0] = indices_idx;
}
Aggregations