Merge "Fix support for @empty in style resolution" into oc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
7d75f49175
@@ -103,7 +103,8 @@ public class TypedArray {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of indices in the array that actually have data.
|
||||
* Returns the number of indices in the array that actually have data. Attributes with a value
|
||||
* of @empty are included, as this is an explicit indicator.
|
||||
*
|
||||
* @throws RuntimeException if the TypedArray has already been recycled.
|
||||
*/
|
||||
@@ -116,7 +117,8 @@ public class TypedArray {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an index in the array that has data.
|
||||
* Returns an index in the array that has data. Attributes with a value of @empty are included,
|
||||
* as this is an explicit indicator.
|
||||
*
|
||||
* @param at The index you would like to returned, ranging from 0 to
|
||||
* {@link #getIndexCount()}.
|
||||
@@ -1017,7 +1019,7 @@ public class TypedArray {
|
||||
* @param outValue TypedValue object in which to place the attribute's
|
||||
* data.
|
||||
*
|
||||
* @return {@code true} if the value was retrieved, false otherwise.
|
||||
* @return {@code true} if the value was retrieved and not @empty, {@code false} otherwise.
|
||||
* @throws RuntimeException if the TypedArray has already been recycled.
|
||||
*/
|
||||
public boolean getValue(@StyleableRes int index, TypedValue outValue) {
|
||||
|
||||
@@ -44,8 +44,7 @@ class XmlAttributeFinder
|
||||
};
|
||||
|
||||
class BagAttributeFinder
|
||||
: public BackTrackingAttributeFinder<BagAttributeFinder,
|
||||
const ResTable::bag_entry*> {
|
||||
: public BackTrackingAttributeFinder<BagAttributeFinder, const ResTable::bag_entry*> {
|
||||
public:
|
||||
BagAttributeFinder(const ResTable::bag_entry* start,
|
||||
const ResTable::bag_entry* end)
|
||||
@@ -76,8 +75,7 @@ bool ResolveAttrs(ResTable::Theme* theme, uint32_t def_style_attr,
|
||||
uint32_t def_style_bag_type_set_flags = 0;
|
||||
if (def_style_attr != 0) {
|
||||
Res_value value;
|
||||
if (theme->getAttribute(def_style_attr, &value,
|
||||
&def_style_bag_type_set_flags) >= 0) {
|
||||
if (theme->getAttribute(def_style_attr, &value, &def_style_bag_type_set_flags) >= 0) {
|
||||
if (value.dataType == Res_value::TYPE_REFERENCE) {
|
||||
def_style_res = value.data;
|
||||
}
|
||||
@@ -127,18 +125,14 @@ bool ResolveAttrs(ResTable::Theme* theme, uint32_t def_style_attr,
|
||||
ALOGI("-> From values: type=0x%x, data=0x%08x", value.dataType,
|
||||
value.data);
|
||||
}
|
||||
}
|
||||
|
||||
if (value.dataType == Res_value::TYPE_NULL) {
|
||||
const ResTable::bag_entry* const def_style_entry =
|
||||
def_style_attr_finder.Find(cur_ident);
|
||||
} else {
|
||||
const ResTable::bag_entry* const def_style_entry = def_style_attr_finder.Find(cur_ident);
|
||||
if (def_style_entry != def_style_end) {
|
||||
block = def_style_entry->stringBlock;
|
||||
type_set_flags = def_style_type_set_flags;
|
||||
value = def_style_entry->map.value;
|
||||
if (kDebugStyles) {
|
||||
ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType,
|
||||
value.data);
|
||||
ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -146,29 +140,24 @@ bool ResolveAttrs(ResTable::Theme* theme, uint32_t def_style_attr,
|
||||
uint32_t resid = 0;
|
||||
if (value.dataType != Res_value::TYPE_NULL) {
|
||||
// Take care of resolving the found resource to its final value.
|
||||
ssize_t new_block = theme->resolveAttributeReference(
|
||||
&value, block, &resid, &type_set_flags, &config);
|
||||
ssize_t new_block =
|
||||
theme->resolveAttributeReference(&value, block, &resid, &type_set_flags, &config);
|
||||
if (new_block >= 0) block = new_block;
|
||||
if (kDebugStyles) {
|
||||
ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType,
|
||||
value.data);
|
||||
ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
|
||||
}
|
||||
} else {
|
||||
} else if (value.data != Res_value::DATA_NULL_EMPTY) {
|
||||
// If we still don't have a value for this attribute, try to find
|
||||
// it in the theme!
|
||||
ssize_t new_block =
|
||||
theme->getAttribute(cur_ident, &value, &type_set_flags);
|
||||
ssize_t new_block = theme->getAttribute(cur_ident, &value, &type_set_flags);
|
||||
if (new_block >= 0) {
|
||||
if (kDebugStyles) {
|
||||
ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType,
|
||||
value.data);
|
||||
ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
|
||||
}
|
||||
new_block = res.resolveReference(&value, new_block, &resid,
|
||||
&type_set_flags, &config);
|
||||
new_block = res.resolveReference(&value, new_block, &resid, &type_set_flags, &config);
|
||||
if (new_block >= 0) block = new_block;
|
||||
if (kDebugStyles) {
|
||||
ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType,
|
||||
value.data);
|
||||
ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -184,8 +173,7 @@ bool ResolveAttrs(ResTable::Theme* theme, uint32_t def_style_attr,
|
||||
}
|
||||
|
||||
if (kDebugStyles) {
|
||||
ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", cur_ident,
|
||||
value.dataType, value.data);
|
||||
ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", cur_ident, value.dataType, value.data);
|
||||
}
|
||||
|
||||
// Write the final value back to Java.
|
||||
@@ -198,7 +186,8 @@ bool ResolveAttrs(ResTable::Theme* theme, uint32_t def_style_attr,
|
||||
out_values[STYLE_CHANGING_CONFIGURATIONS] = type_set_flags;
|
||||
out_values[STYLE_DENSITY] = config.density;
|
||||
|
||||
if (out_indices != nullptr && value.dataType != Res_value::TYPE_NULL) {
|
||||
if (out_indices != nullptr &&
|
||||
(value.dataType != Res_value::TYPE_NULL || value.data == Res_value::DATA_NULL_EMPTY)) {
|
||||
indices_idx++;
|
||||
out_indices[indices_idx] = ii;
|
||||
}
|
||||
@@ -247,8 +236,7 @@ void ApplyStyle(ResTable::Theme* theme, ResXMLParser* xml_parser, uint32_t def_s
|
||||
ssize_t idx = xml_parser->indexOfStyle();
|
||||
if (idx >= 0 && xml_parser->getAttributeValue(idx, &value) >= 0) {
|
||||
if (value.dataType == value.TYPE_ATTRIBUTE) {
|
||||
if (theme->getAttribute(value.data, &value, &style_bag_type_set_flags) <
|
||||
0) {
|
||||
if (theme->getAttribute(value.data, &value, &style_bag_type_set_flags) < 0) {
|
||||
value.dataType = Res_value::TYPE_NULL;
|
||||
}
|
||||
}
|
||||
@@ -318,41 +306,34 @@ void ApplyStyle(ResTable::Theme* theme, ResXMLParser* xml_parser, uint32_t def_s
|
||||
// We found the attribute we were looking for.
|
||||
xml_parser->getAttributeValue(xml_attr_idx, &value);
|
||||
if (kDebugStyles) {
|
||||
ALOGI("-> From XML: type=0x%x, data=0x%08x", value.dataType,
|
||||
value.data);
|
||||
ALOGI("-> From XML: type=0x%x, data=0x%08x", value.dataType, value.data);
|
||||
}
|
||||
}
|
||||
|
||||
if (value.dataType == Res_value::TYPE_NULL) {
|
||||
// Walk through the style class values looking for the requested
|
||||
// attribute.
|
||||
const ResTable::bag_entry* const style_attr_entry =
|
||||
style_attr_finder.Find(cur_ident);
|
||||
if (value.dataType == Res_value::TYPE_NULL && value.data != Res_value::DATA_NULL_EMPTY) {
|
||||
// Walk through the style class values looking for the requested attribute.
|
||||
const ResTable::bag_entry* const style_attr_entry = style_attr_finder.Find(cur_ident);
|
||||
if (style_attr_entry != style_attr_end) {
|
||||
// We found the attribute we were looking for.
|
||||
block = style_attr_entry->stringBlock;
|
||||
type_set_flags = style_type_set_flags;
|
||||
value = style_attr_entry->map.value;
|
||||
if (kDebugStyles) {
|
||||
ALOGI("-> From style: type=0x%x, data=0x%08x", value.dataType,
|
||||
value.data);
|
||||
ALOGI("-> From style: type=0x%x, data=0x%08x", value.dataType, value.data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (value.dataType == Res_value::TYPE_NULL) {
|
||||
// Walk through the default style values looking for the requested
|
||||
// attribute.
|
||||
const ResTable::bag_entry* const def_style_attr_entry =
|
||||
def_style_attr_finder.Find(cur_ident);
|
||||
if (value.dataType == Res_value::TYPE_NULL && value.data != Res_value::DATA_NULL_EMPTY) {
|
||||
// Walk through the default style values looking for the requested attribute.
|
||||
const ResTable::bag_entry* const def_style_attr_entry = def_style_attr_finder.Find(cur_ident);
|
||||
if (def_style_attr_entry != def_style_attr_end) {
|
||||
// We found the attribute we were looking for.
|
||||
block = def_style_attr_entry->stringBlock;
|
||||
type_set_flags = style_type_set_flags;
|
||||
value = def_style_attr_entry->map.value;
|
||||
if (kDebugStyles) {
|
||||
ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType,
|
||||
value.data);
|
||||
ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -360,35 +341,29 @@ void ApplyStyle(ResTable::Theme* theme, ResXMLParser* xml_parser, uint32_t def_s
|
||||
uint32_t resid = 0;
|
||||
if (value.dataType != Res_value::TYPE_NULL) {
|
||||
// Take care of resolving the found resource to its final value.
|
||||
ssize_t new_block = theme->resolveAttributeReference(
|
||||
&value, block, &resid, &type_set_flags, &config);
|
||||
ssize_t new_block =
|
||||
theme->resolveAttributeReference(&value, block, &resid, &type_set_flags, &config);
|
||||
if (new_block >= 0) {
|
||||
block = new_block;
|
||||
}
|
||||
|
||||
if (kDebugStyles) {
|
||||
ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType,
|
||||
value.data);
|
||||
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!
|
||||
ssize_t new_block =
|
||||
theme->getAttribute(cur_ident, &value, &type_set_flags);
|
||||
} else if (value.data != Res_value::DATA_NULL_EMPTY) {
|
||||
// If we still don't have a value for this attribute, try to find it in the theme!
|
||||
ssize_t new_block = theme->getAttribute(cur_ident, &value, &type_set_flags);
|
||||
if (new_block >= 0) {
|
||||
if (kDebugStyles) {
|
||||
ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType,
|
||||
value.data);
|
||||
ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
|
||||
}
|
||||
new_block = res.resolveReference(&value, new_block, &resid,
|
||||
&type_set_flags, &config);
|
||||
new_block = res.resolveReference(&value, new_block, &resid, &type_set_flags, &config);
|
||||
if (new_block >= 0) {
|
||||
block = new_block;
|
||||
}
|
||||
|
||||
if (kDebugStyles) {
|
||||
ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType,
|
||||
value.data);
|
||||
ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -404,8 +379,7 @@ void ApplyStyle(ResTable::Theme* theme, ResXMLParser* xml_parser, uint32_t def_s
|
||||
}
|
||||
|
||||
if (kDebugStyles) {
|
||||
ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", cur_ident,
|
||||
value.dataType, value.data);
|
||||
ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", cur_ident, value.dataType, value.data);
|
||||
}
|
||||
|
||||
// Write the final value back to Java.
|
||||
@@ -418,7 +392,7 @@ void ApplyStyle(ResTable::Theme* theme, ResXMLParser* xml_parser, uint32_t def_s
|
||||
out_values[STYLE_CHANGING_CONFIGURATIONS] = type_set_flags;
|
||||
out_values[STYLE_DENSITY] = config.density;
|
||||
|
||||
if (value.dataType != Res_value::TYPE_NULL) {
|
||||
if (value.dataType != Res_value::TYPE_NULL || value.data == Res_value::DATA_NULL_EMPTY) {
|
||||
indices_idx++;
|
||||
|
||||
// out_indices must NOT be nullptr.
|
||||
@@ -502,7 +476,8 @@ bool RetrieveAttributes(const ResTable* res, ResXMLParser* xml_parser,
|
||||
out_values[STYLE_CHANGING_CONFIGURATIONS] = type_set_flags;
|
||||
out_values[STYLE_DENSITY] = config.density;
|
||||
|
||||
if (out_indices != nullptr && value.dataType != Res_value::TYPE_NULL) {
|
||||
if (out_indices != nullptr &&
|
||||
(value.dataType != Res_value::TYPE_NULL || value.data == Res_value::DATA_NULL_EMPTY)) {
|
||||
indices_idx++;
|
||||
out_indices[indices_idx] = ii;
|
||||
}
|
||||
|
||||
@@ -3538,7 +3538,8 @@ status_t ResTable::Theme::applyStyle(uint32_t resID, bool force)
|
||||
attrRes, bag->map.value.dataType, bag->map.value.data,
|
||||
curEntry->value.dataType);
|
||||
}
|
||||
if (force || curEntry->value.dataType == Res_value::TYPE_NULL) {
|
||||
if (force || (curEntry->value.dataType == Res_value::TYPE_NULL
|
||||
&& curEntry->value.data != Res_value::DATA_NULL_EMPTY)) {
|
||||
curEntry->stringBlock = bag->stringBlock;
|
||||
curEntry->typeSpecFlags |= bagTypeSpecFlags;
|
||||
curEntry->value = bag->map.value;
|
||||
@@ -3674,7 +3675,8 @@ ssize_t ResTable::Theme::getAttribute(uint32_t resID, Res_value* outValue,
|
||||
}
|
||||
ALOGW("Too many attribute references, stopped at: 0x%08x\n", resID);
|
||||
return BAD_INDEX;
|
||||
} else if (type != Res_value::TYPE_NULL) {
|
||||
} else if (type != Res_value::TYPE_NULL
|
||||
|| te.value.data == Res_value::DATA_NULL_EMPTY) {
|
||||
*outValue = te.value;
|
||||
return te.stringBlock;
|
||||
}
|
||||
|
||||
@@ -264,7 +264,7 @@ TEST_F(AssetManager2Test, MergesStylesWithParentFromSingleApkAssets) {
|
||||
|
||||
const ResolvedBag* bag_two = assetmanager.GetBag(app::R::style::StyleTwo);
|
||||
ASSERT_NE(nullptr, bag_two);
|
||||
ASSERT_EQ(5u, bag_two->entry_count);
|
||||
ASSERT_EQ(6u, bag_two->entry_count);
|
||||
|
||||
// attr_one is inherited from StyleOne.
|
||||
EXPECT_EQ(app::R::attr::attr_one, bag_two->entries[0].key);
|
||||
@@ -295,6 +295,11 @@ TEST_F(AssetManager2Test, MergesStylesWithParentFromSingleApkAssets) {
|
||||
EXPECT_EQ(Res_value::TYPE_INT_DEC, bag_two->entries[4].value.dataType);
|
||||
EXPECT_EQ(3u, bag_two->entries[4].value.data);
|
||||
EXPECT_EQ(0, bag_two->entries[4].cookie);
|
||||
|
||||
EXPECT_EQ(app::R::attr::attr_empty, bag_two->entries[5].key);
|
||||
EXPECT_EQ(Res_value::TYPE_NULL, bag_two->entries[5].value.dataType);
|
||||
EXPECT_EQ(Res_value::DATA_NULL_EMPTY, bag_two->entries[5].value.data);
|
||||
EXPECT_EQ(0, bag_two->entries[5].cookie);
|
||||
}
|
||||
|
||||
TEST_F(AssetManager2Test, ResolveReferenceToResource) {
|
||||
|
||||
@@ -69,8 +69,8 @@ TEST_F(AttributeResolutionTest, Theme) {
|
||||
ResTable::Theme theme(table_);
|
||||
ASSERT_EQ(NO_ERROR, theme.applyStyle(R::style::StyleTwo));
|
||||
|
||||
std::array<uint32_t, 4> attrs{
|
||||
{R::attr::attr_one, R::attr::attr_two, R::attr::attr_three, R::attr::attr_four}};
|
||||
std::array<uint32_t, 5> attrs{{R::attr::attr_one, R::attr::attr_two, R::attr::attr_three,
|
||||
R::attr::attr_four, R::attr::attr_empty}};
|
||||
std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values;
|
||||
|
||||
ASSERT_TRUE(ResolveAttrs(&theme, 0 /*def_style_attr*/, 0 /*def_style_res*/,
|
||||
@@ -109,11 +109,21 @@ TEST_F(AttributeResolutionTest, Theme) {
|
||||
EXPECT_EQ(uint32_t(-1), values_cursor[STYLE_ASSET_COOKIE]);
|
||||
EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
|
||||
EXPECT_EQ(0u, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);
|
||||
|
||||
// @empty comes from the theme, so it has the same asset cookie and changing configurations flags
|
||||
// as the theme.
|
||||
values_cursor += STYLE_NUM_ENTRIES;
|
||||
EXPECT_EQ(Res_value::TYPE_NULL, values_cursor[STYLE_TYPE]);
|
||||
EXPECT_EQ(Res_value::DATA_NULL_EMPTY, values_cursor[STYLE_DATA]);
|
||||
EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]);
|
||||
EXPECT_EQ(1u, values_cursor[STYLE_ASSET_COOKIE]);
|
||||
EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
|
||||
EXPECT_EQ(public_flag, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);
|
||||
}
|
||||
|
||||
TEST_F(AttributeResolutionXmlTest, XmlParser) {
|
||||
std::array<uint32_t, 4> attrs{
|
||||
{R::attr::attr_one, R::attr::attr_two, R::attr::attr_three, R::attr::attr_four}};
|
||||
std::array<uint32_t, 5> attrs{{R::attr::attr_one, R::attr::attr_two, R::attr::attr_three,
|
||||
R::attr::attr_four, R::attr::attr_empty}};
|
||||
std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values;
|
||||
|
||||
ASSERT_TRUE(RetrieveAttributes(&table_, &xml_parser_, attrs.data(), attrs.size(), values.data(),
|
||||
@@ -121,7 +131,7 @@ TEST_F(AttributeResolutionXmlTest, XmlParser) {
|
||||
|
||||
uint32_t* values_cursor = values.data();
|
||||
EXPECT_EQ(Res_value::TYPE_NULL, values_cursor[STYLE_TYPE]);
|
||||
EXPECT_EQ(0u, values_cursor[STYLE_DATA]);
|
||||
EXPECT_EQ(Res_value::DATA_NULL_EMPTY, values_cursor[STYLE_DATA]);
|
||||
EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]);
|
||||
EXPECT_EQ(uint32_t(-1), values_cursor[STYLE_ASSET_COOKIE]);
|
||||
EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
|
||||
@@ -150,16 +160,24 @@ TEST_F(AttributeResolutionXmlTest, XmlParser) {
|
||||
EXPECT_EQ(uint32_t(-1), values_cursor[STYLE_ASSET_COOKIE]);
|
||||
EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
|
||||
EXPECT_EQ(0u, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);
|
||||
|
||||
values_cursor += STYLE_NUM_ENTRIES;
|
||||
EXPECT_EQ(Res_value::TYPE_NULL, values_cursor[STYLE_TYPE]);
|
||||
EXPECT_EQ(Res_value::DATA_NULL_UNDEFINED, values_cursor[STYLE_DATA]);
|
||||
EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]);
|
||||
EXPECT_EQ(uint32_t(-1), values_cursor[STYLE_ASSET_COOKIE]);
|
||||
EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
|
||||
EXPECT_EQ(0u, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);
|
||||
}
|
||||
|
||||
TEST_F(AttributeResolutionXmlTest, ThemeAndXmlParser) {
|
||||
ResTable::Theme theme(table_);
|
||||
ASSERT_EQ(NO_ERROR, theme.applyStyle(R::style::StyleTwo));
|
||||
|
||||
std::array<uint32_t, 5> attrs{{R::attr::attr_one, R::attr::attr_two, R::attr::attr_three,
|
||||
R::attr::attr_four, R::attr::attr_five}};
|
||||
std::array<uint32_t, 6> attrs{{R::attr::attr_one, R::attr::attr_two, R::attr::attr_three,
|
||||
R::attr::attr_four, R::attr::attr_five, R::attr::attr_empty}};
|
||||
std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values;
|
||||
std::array<uint32_t, attrs.size()> indices;
|
||||
std::array<uint32_t, attrs.size() + 1> indices;
|
||||
|
||||
ApplyStyle(&theme, &xml_parser_, 0 /*def_style_attr*/, 0 /*def_style_res*/, attrs.data(),
|
||||
attrs.size(), values.data(), indices.data());
|
||||
@@ -167,12 +185,12 @@ TEST_F(AttributeResolutionXmlTest, ThemeAndXmlParser) {
|
||||
const uint32_t public_flag = ResTable_typeSpec::SPEC_PUBLIC;
|
||||
|
||||
uint32_t* values_cursor = values.data();
|
||||
EXPECT_EQ(Res_value::TYPE_INT_DEC, values_cursor[STYLE_TYPE]);
|
||||
EXPECT_EQ(1u, values_cursor[STYLE_DATA]);
|
||||
EXPECT_EQ(Res_value::TYPE_NULL, values_cursor[STYLE_TYPE]);
|
||||
EXPECT_EQ(Res_value::DATA_NULL_EMPTY, values_cursor[STYLE_DATA]);
|
||||
EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]);
|
||||
EXPECT_EQ(1u, values_cursor[STYLE_ASSET_COOKIE]);
|
||||
EXPECT_EQ(uint32_t(-1), values_cursor[STYLE_ASSET_COOKIE]);
|
||||
EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
|
||||
EXPECT_EQ(public_flag, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);
|
||||
EXPECT_EQ(0u, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);
|
||||
|
||||
values_cursor += STYLE_NUM_ENTRIES;
|
||||
EXPECT_EQ(Res_value::TYPE_STRING, values_cursor[STYLE_TYPE]);
|
||||
@@ -203,6 +221,20 @@ TEST_F(AttributeResolutionXmlTest, ThemeAndXmlParser) {
|
||||
EXPECT_EQ(1u, values_cursor[STYLE_ASSET_COOKIE]);
|
||||
EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
|
||||
EXPECT_EQ(public_flag, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);
|
||||
|
||||
// @empty comes from the theme, so it has the same asset cookie and changing configurations flags
|
||||
// as the theme.
|
||||
values_cursor += STYLE_NUM_ENTRIES;
|
||||
EXPECT_EQ(Res_value::TYPE_NULL, values_cursor[STYLE_TYPE]);
|
||||
EXPECT_EQ(Res_value::DATA_NULL_EMPTY, values_cursor[STYLE_DATA]);
|
||||
EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]);
|
||||
EXPECT_EQ(1u, values_cursor[STYLE_ASSET_COOKIE]);
|
||||
EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
|
||||
EXPECT_EQ(public_flag, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);
|
||||
|
||||
// The first element of indices contains the number of indices.
|
||||
std::array<uint32_t, 7> expected_indices = {{6u, 0u, 1u, 2u, 3u, 4u, 5u}};
|
||||
EXPECT_EQ(expected_indices, indices);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
|
||||
@@ -33,6 +33,7 @@ struct R {
|
||||
attr_five = 0x7f010004u,
|
||||
attr_indirect = 0x7f010005u,
|
||||
attr_six = 0x7f010006u,
|
||||
attr_empty = 0x7f010007u,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -2,4 +2,5 @@
|
||||
|
||||
set -e
|
||||
|
||||
aapt package -F styles.apk -M AndroidManifest.xml -S res -f
|
||||
aapt2 compile -o compiled.flata --dir res
|
||||
aapt2 link -o styles.apk --manifest AndroidManifest.xml compiled.flata
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<View xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
app:attr_four="?attr/attr_indirect"
|
||||
app:attr_three="10" />
|
||||
|
||||
app:attr_three="10"
|
||||
app:attr_one="@empty" />
|
||||
|
||||
@@ -33,6 +33,12 @@
|
||||
<public type="attr" name="attr_indirect" id="0x7f010005" />
|
||||
<attr name="attr_indirect" />
|
||||
|
||||
<public type="attr" name="attr_six" id="0x7f010006" />
|
||||
<attr name="attr_six" />
|
||||
|
||||
<public type="attr" name="attr_empty" id="0x7f010007" />
|
||||
<attr name="attr_empty" />
|
||||
|
||||
<public type="string" name="string_one" id="0x7f030000" />
|
||||
<string name="string_one">Hi</string>
|
||||
|
||||
@@ -48,11 +54,9 @@
|
||||
<item name="attr_two">"string"</item>
|
||||
<item name="attr_three">?attr/attr_indirect</item>
|
||||
<item name="attr_five">@string/string_one</item>
|
||||
<item name="attr_empty">@empty</item>
|
||||
</style>
|
||||
|
||||
<public type="attr" name="attr_six" id="0x7f010006" />
|
||||
<attr name="attr_six" />
|
||||
|
||||
|
||||
<public type="style" name="StyleThree" id="0x7f020002" />
|
||||
<style name="StyleThree">
|
||||
<item name="attr_six">6</item>
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user