Set resource id correctly when resolve fails am: e7ab62723a am: 9e78098e85

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1519910

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: I25318a316ae24d3f587009c688f7e830b7c00c2b
This commit is contained in:
Ryan Mitchell
2020-12-14 22:25:06 +00:00
committed by Automerger Merge Worker
3 changed files with 44 additions and 8 deletions

View File

@@ -975,19 +975,23 @@ base::expected<std::monostate, NullOrIOError> AssetManager2::ResolveReference(
for (uint32_t i = 0U;; i++) {
auto result = GetResource(resolve_resid, true /*may_be_bag*/);
if (!result.has_value()) {
value.resid = resolve_resid;
return base::unexpected(result.error());
}
// If resource resolution fails, the value should be set to the last reference that was able to
// be resolved successfully.
value = *result;
value.flags |= combined_flags;
if (result->type != Res_value::TYPE_REFERENCE ||
result->data == Res_value::DATA_NULL_UNDEFINED ||
result->data == resolve_resid || i == kMaxIterations) {
// This reference can't be resolved, so exit now and let the caller deal with it.
value = *result;
value.flags |= combined_flags;
return {};
}
combined_flags |= result->flags;
combined_flags = result->flags;
resolve_resid = result->data;
}
}

View File

@@ -265,7 +265,7 @@ base::expected<std::monostate, IOError> ApplyStyle(Theme* theme, ResXMLParser* x
const size_t xml_attr_idx = xml_attr_finder.Find(cur_ident);
if (xml_attr_idx != xml_attr_finder.end()) {
// We found the attribute we were looking for.
Res_value attribute_value;
Res_value attribute_value{};
xml_parser->getAttributeValue(xml_attr_idx, &attribute_value);
value.type = attribute_value.dataType;
value.data = attribute_value.data;
@@ -377,7 +377,7 @@ base::expected<std::monostate, IOError> RetrieveAttributes(AssetManager2* assetm
// Retrieve the current XML attribute if it matches, and step to next.
if (ix < xml_attr_count && cur_ident == cur_xml_attr) {
Res_value attribute_value;
Res_value attribute_value{};
xml_parser->getAttributeValue(ix, &attribute_value);
value.type = attribute_value.dataType;
value.data = attribute_value.data;

View File

@@ -446,9 +446,6 @@ TEST_F(AssetManager2Test, KeepLastReferenceIdUnmodifiedIfNoReferenceIsResolved)
AssetManager2 assetmanager;
assetmanager.SetApkAssets({basic_assets_.get()});
ResTable_config selected_config;
memset(&selected_config, 0, sizeof(selected_config));
// Create some kind of value that is NOT a reference.
AssetManager2::SelectedValue value{};
value.cookie = 1;
@@ -461,6 +458,41 @@ TEST_F(AssetManager2Test, KeepLastReferenceIdUnmodifiedIfNoReferenceIsResolved)
EXPECT_EQ(basic::R::string::test1, value.resid);
}
TEST_F(AssetManager2Test, ResolveReferenceMissingResource) {
AssetManager2 assetmanager;
assetmanager.SetApkAssets({basic_assets_.get()});
const uint32_t kMissingResId = 0x8001ffff;
AssetManager2::SelectedValue value{};
value.type = Res_value::TYPE_REFERENCE;
value.data = kMissingResId;
auto result = assetmanager.ResolveReference(value);
ASSERT_FALSE(result.has_value());
EXPECT_EQ(Res_value::TYPE_REFERENCE, value.type);
EXPECT_EQ(kMissingResId, value.data);
EXPECT_EQ(kMissingResId, value.resid);
EXPECT_EQ(-1, value.cookie);
EXPECT_EQ(0, value.flags);
}
TEST_F(AssetManager2Test, ResolveReferenceMissingResourceLib) {
AssetManager2 assetmanager;
assetmanager.SetApkAssets({libclient_assets_.get()});
AssetManager2::SelectedValue value{};
value.type = Res_value::TYPE_REFERENCE;
value.data = libclient::R::string::foo_one;
auto result = assetmanager.ResolveReference(value);
ASSERT_TRUE(result.has_value());
EXPECT_EQ(Res_value::TYPE_DYNAMIC_REFERENCE, value.type);
EXPECT_EQ(lib_one::R::string::foo, value.data);
EXPECT_EQ(libclient::R::string::foo_one, value.resid);
EXPECT_EQ(0, value.cookie);
EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), value.flags);
}
static bool IsConfigurationPresent(const std::set<ResTable_config>& configurations,
const ResTable_config& configuration) {
return configurations.count(configuration) > 0;