summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libs/androidfw/AssetManager2.cpp10
-rw-r--r--libs/androidfw/AttributeResolution.cpp4
-rw-r--r--libs/androidfw/tests/AssetManager2_test.cpp38
3 files changed, 44 insertions, 8 deletions
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index 3e54dc67db76..8bab73cd15f0 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -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;
}
}
diff --git a/libs/androidfw/AttributeResolution.cpp b/libs/androidfw/AttributeResolution.cpp
index 71919fdbb736..d07b452ad40e 100644
--- a/libs/androidfw/AttributeResolution.cpp
+++ b/libs/androidfw/AttributeResolution.cpp
@@ -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;
diff --git a/libs/androidfw/tests/AssetManager2_test.cpp b/libs/androidfw/tests/AssetManager2_test.cpp
index 3638ce1f92d7..0f5afd45546c 100644
--- a/libs/androidfw/tests/AssetManager2_test.cpp
+++ b/libs/androidfw/tests/AssetManager2_test.cpp
@@ -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;