Set resource id correctly when resolve fails am: e7ab62723a
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1519910 MUST ONLY BE SUBMITTED BY AUTOMERGER Change-Id: I0e4decf7a7f9b1e4d6c1b6fb45f37d105c15b9a0
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user