AssetManager2: Add GetResourceId
Add ability to lookup a resource by name.
Test: make libandroidfw_tests
Change-Id: I262ba5ce4c9892458226fbdb44cf21f9877fb92d
diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp
index ecf6bd4..e764034 100644
--- a/libs/androidfw/Android.bp
+++ b/libs/androidfw/Android.bp
@@ -36,6 +36,7 @@
"misc.cpp",
"ObbFile.cpp",
"ResourceTypes.cpp",
+ "ResourceUtils.cpp",
"StreamingZipInflater.cpp",
"TypeWrappers.cpp",
"Util.cpp",
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index 542a125..ef0c967 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -31,6 +31,8 @@
#endif
#endif
+#include "androidfw/ResourceUtils.h"
+
namespace android {
AssetManager2::AssetManager2() { memset(&configuration_, 0, sizeof(configuration_)); }
@@ -235,9 +237,9 @@
desired_config = &density_override_config;
}
- const uint32_t package_id = util::get_package_id(resid);
- const uint8_t type_id = util::get_type_id(resid);
- const uint16_t entry_id = util::get_entry_id(resid);
+ const uint32_t package_id = get_package_id(resid);
+ const uint8_t type_id = get_type_id(resid);
+ const uint16_t entry_id = get_entry_id(resid);
if (type_id == 0) {
LOG(ERROR) << base::StringPrintf("Invalid ID 0x%08x.", resid);
@@ -452,7 +454,7 @@
ResolvedBag::Entry* new_entry = new_bag->entries;
for (; map_entry != map_entry_end; ++map_entry) {
uint32_t new_key = dtohl(map_entry->name.ident);
- if (!util::is_internal_resid(new_key)) {
+ if (!is_internal_resid(new_key)) {
// Attributes, arrays, etc don't have a resource id as the name. They specify
// other data, which would be wrong to change via a lookup.
if (entry.dynamic_ref_table->lookupResourceId(&new_key) != NO_ERROR) {
@@ -501,7 +503,7 @@
// The keys are expected to be in sorted order. Merge the two bags.
while (map_entry != map_entry_end && parent_entry != parent_entry_end) {
uint32_t child_key = dtohl(map_entry->name.ident);
- if (!util::is_internal_resid(child_key)) {
+ if (!is_internal_resid(child_key)) {
if (entry.dynamic_ref_table->lookupResourceId(&child_key) != NO_ERROR) {
LOG(ERROR) << base::StringPrintf("Failed to resolve key 0x%08x in bag 0x%08x.", child_key, resid);
return nullptr;
@@ -533,7 +535,7 @@
// Finish the child entries if they exist.
while (map_entry != map_entry_end) {
uint32_t new_key = dtohl(map_entry->name.ident);
- if (!util::is_internal_resid(new_key)) {
+ if (!is_internal_resid(new_key)) {
if (entry.dynamic_ref_table->lookupResourceId(&new_key) != NO_ERROR) {
LOG(ERROR) << base::StringPrintf("Failed to resolve key 0x%08x in bag 0x%08x.", new_key, resid);
return nullptr;
@@ -571,12 +573,71 @@
return result;
}
+static bool Utf8ToUtf16(const StringPiece& str, std::u16string* out) {
+ ssize_t len =
+ utf8_to_utf16_length(reinterpret_cast<const uint8_t*>(str.data()), str.size(), false);
+ if (len < 0) {
+ return false;
+ }
+ out->resize(static_cast<size_t>(len));
+ utf8_to_utf16(reinterpret_cast<const uint8_t*>(str.data()), str.size(), &*out->begin(),
+ static_cast<size_t>(len + 1));
+ return true;
+}
+
uint32_t AssetManager2::GetResourceId(const std::string& resource_name,
const std::string& fallback_type,
const std::string& fallback_package) {
- (void)resource_name;
- (void)fallback_type;
- (void)fallback_package;
+ StringPiece package_name, type, entry;
+ if (!ExtractResourceName(resource_name, &package_name, &type, &entry)) {
+ return 0u;
+ }
+
+ if (entry.empty()) {
+ return 0u;
+ }
+
+ if (package_name.empty()) {
+ package_name = fallback_package;
+ }
+
+ if (type.empty()) {
+ type = fallback_type;
+ }
+
+ std::u16string type16;
+ if (!Utf8ToUtf16(type, &type16)) {
+ return 0u;
+ }
+
+ std::u16string entry16;
+ if (!Utf8ToUtf16(entry, &entry16)) {
+ return 0u;
+ }
+
+ const StringPiece16 kAttr16 = u"attr";
+ const static std::u16string kAttrPrivate16 = u"^attr-private";
+
+ for (const PackageGroup& package_group : package_groups_) {
+ for (const LoadedPackage* package : package_group.packages_) {
+ if (package_name != package->GetPackageName()) {
+ // All packages in the same group are expected to have the same package name.
+ break;
+ }
+
+ uint32_t resid = package->FindEntryByName(type16, entry16);
+ if (resid == 0u && kAttr16 == type16) {
+ // Private attributes in libraries (such as the framework) are sometimes encoded
+ // under the type '^attr-private' in order to leave the ID space of public 'attr'
+ // free for future additions. Check '^attr-private' for the same name.
+ resid = package->FindEntryByName(kAttrPrivate16, entry16);
+ }
+
+ if (resid != 0u) {
+ return fix_package_id(resid, package_group.dynamic_ref_table.mAssignedPackageId);
+ }
+ }
+ }
return 0u;
}
@@ -619,15 +680,15 @@
// If the resource ID passed in is not a style, the key can be
// some other identifier that is not a resource ID.
- if (!util::is_valid_resid(attr_resid)) {
+ if (!is_valid_resid(attr_resid)) {
return false;
}
- const uint32_t package_idx = util::get_package_id(attr_resid);
+ const uint32_t package_idx = get_package_id(attr_resid);
// The type ID is 1-based, so subtract 1 to get an index.
- const uint32_t type_idx = util::get_type_id(attr_resid) - 1;
- const uint32_t entry_idx = util::get_entry_id(attr_resid);
+ const uint32_t type_idx = get_type_id(attr_resid) - 1;
+ const uint32_t entry_idx = get_entry_id(attr_resid);
std::unique_ptr<Package>& package = packages_[package_idx];
if (package == nullptr) {
@@ -656,9 +717,9 @@
// and populate the structures.
for (auto bag_iter = begin(bag); bag_iter != bag_iter_end; ++bag_iter) {
const uint32_t attr_resid = bag_iter->key;
- const uint32_t package_idx = util::get_package_id(attr_resid);
- const uint32_t type_idx = util::get_type_id(attr_resid) - 1;
- const uint32_t entry_idx = util::get_entry_id(attr_resid);
+ const uint32_t package_idx = get_package_id(attr_resid);
+ const uint32_t type_idx = get_type_id(attr_resid) - 1;
+ const uint32_t entry_idx = get_entry_id(attr_resid);
Package* package = packages_[package_idx].get();
util::unique_cptr<Type>& type = package->types[type_idx];
if (type->entry_count != type->entry_capacity) {
@@ -691,15 +752,15 @@
uint32_t type_spec_flags = 0u;
for (int iterations_left = kMaxIterations; iterations_left > 0; iterations_left--) {
- if (!util::is_valid_resid(resid)) {
+ if (!is_valid_resid(resid)) {
return kInvalidCookie;
}
- const uint32_t package_idx = util::get_package_id(resid);
+ const uint32_t package_idx = get_package_id(resid);
// Type ID is 1-based, subtract 1 to get the index.
- const uint32_t type_idx = util::get_type_id(resid) - 1;
- const uint32_t entry_idx = util::get_entry_id(resid);
+ const uint32_t type_idx = get_type_id(resid) - 1;
+ const uint32_t entry_idx = get_entry_id(resid);
const Package* package = packages_[package_idx].get();
if (package == nullptr) {
diff --git a/libs/androidfw/LoadedArsc.cpp b/libs/androidfw/LoadedArsc.cpp
index cb589ec..db72f48 100644
--- a/libs/androidfw/LoadedArsc.cpp
+++ b/libs/androidfw/LoadedArsc.cpp
@@ -34,6 +34,7 @@
#include "androidfw/ByteBucketArray.h"
#include "androidfw/Chunk.h"
+#include "androidfw/ResourceUtils.h"
#include "androidfw/Util.h"
using android::base::StringPrintf;
@@ -181,9 +182,9 @@
LoadedArscEntry* out_entry, ResTable_config* out_selected_config,
uint32_t* out_flags) const {
ATRACE_CALL();
- const uint8_t package_id = util::get_package_id(resid);
- const uint8_t type_id = util::get_type_id(resid);
- const uint16_t entry_id = util::get_entry_id(resid);
+ const uint8_t package_id = get_package_id(resid);
+ const uint8_t type_id = get_type_id(resid);
+ const uint16_t entry_id = get_entry_id(resid);
if (type_id == 0) {
LOG(ERROR) << "Invalid ID 0x" << std::hex << resid << std::dec << ".";
@@ -200,7 +201,7 @@
}
const LoadedPackage* LoadedArsc::GetPackageForId(uint32_t resid) const {
- const uint8_t package_id = util::get_package_id(resid);
+ const uint8_t package_id = get_package_id(resid);
for (const auto& loaded_package : packages_) {
if (loaded_package->package_id_ == package_id) {
return loaded_package.get();
@@ -372,6 +373,45 @@
}
}
+uint32_t LoadedPackage::FindEntryByName(const std::u16string& type_name,
+ const std::u16string& entry_name) const {
+ ssize_t type_idx = type_string_pool_.indexOfString(type_name.data(), type_name.size());
+ if (type_idx < 0) {
+ return 0u;
+ }
+
+ ssize_t key_idx = key_string_pool_.indexOfString(entry_name.data(), entry_name.size());
+ if (key_idx < 0) {
+ return 0u;
+ }
+
+ const TypeSpec* type_spec = type_specs_[type_idx].get();
+ if (type_spec == nullptr) {
+ return 0u;
+ }
+
+ for (size_t ti = 0; ti < type_spec->type_count; ti++) {
+ const Type* type = &type_spec->types[ti];
+ size_t entry_count = dtohl(type->type->entryCount);
+ for (size_t entry_idx = 0; entry_idx < entry_count; entry_idx++) {
+ const uint32_t* entry_offsets = reinterpret_cast<const uint32_t*>(
+ reinterpret_cast<const uint8_t*>(type->type) + dtohs(type->type->header.headerSize));
+ const uint32_t offset = dtohl(entry_offsets[entry_idx]);
+ if (offset != ResTable_type::NO_ENTRY) {
+ const ResTable_entry* entry =
+ reinterpret_cast<const ResTable_entry*>(reinterpret_cast<const uint8_t*>(type->type) +
+ dtohl(type->type->entriesStart) + offset);
+ if (dtohl(entry->key.index) == static_cast<uint32_t>(key_idx)) {
+ // The package ID will be overridden by the caller (due to runtime assignment of package
+ // IDs for shared libraries).
+ return make_resid(0x00, type_idx + type_id_offset_ + 1, entry_idx);
+ }
+ }
+ }
+ }
+ return 0u;
+}
+
std::unique_ptr<LoadedPackage> LoadedPackage::Load(const Chunk& chunk) {
ATRACE_CALL();
std::unique_ptr<LoadedPackage> loaded_package{new LoadedPackage()};
diff --git a/libs/androidfw/ResourceUtils.cpp b/libs/androidfw/ResourceUtils.cpp
new file mode 100644
index 0000000..1aa6cf6
--- /dev/null
+++ b/libs/androidfw/ResourceUtils.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "androidfw/ResourceUtils.h"
+
+namespace android {
+
+bool ExtractResourceName(const StringPiece& str, StringPiece* out_package, StringPiece* out_type,
+ StringPiece* out_entry) {
+ *out_package = "";
+ *out_type = "";
+ bool has_package_separator = false;
+ bool has_type_separator = false;
+ const char* start = str.data();
+ const char* end = start + str.size();
+ const char* current = start;
+ while (current != end) {
+ if (out_type->size() == 0 && *current == '/') {
+ has_type_separator = true;
+ out_type->assign(start, current - start);
+ start = current + 1;
+ } else if (out_package->size() == 0 && *current == ':') {
+ has_package_separator = true;
+ out_package->assign(start, current - start);
+ start = current + 1;
+ }
+ current++;
+ }
+ out_entry->assign(start, end - start);
+
+ return !(has_package_separator && out_package->empty()) &&
+ !(has_type_separator && out_type->empty());
+}
+
+} // namespace android
diff --git a/libs/androidfw/include/androidfw/LoadedArsc.h b/libs/androidfw/include/androidfw/LoadedArsc.h
index 91a7cb7..f30b158 100644
--- a/libs/androidfw/include/androidfw/LoadedArsc.h
+++ b/libs/androidfw/include/androidfw/LoadedArsc.h
@@ -101,6 +101,13 @@
// before being inserted into the set. This may cause some equivalent locales to de-dupe.
void CollectLocales(bool canonicalize, std::set<std::string>* out_locales) const;
+ // Finds the entry with the specified type name and entry name. The names are in UTF-16 because
+ // the underlying ResStringPool API expects this. For now this is acceptable, but since
+ // the default policy in AAPT2 is to build UTF-8 string pools, this needs to change.
+ // Returns a partial resource ID, with the package ID left as 0x00. The caller is responsible
+ // for patching the correct package ID to the resource ID.
+ uint32_t FindEntryByName(const std::u16string& type_name, const std::u16string& entry_name) const;
+
private:
DISALLOW_COPY_AND_ASSIGN(LoadedPackage);
diff --git a/libs/androidfw/include/androidfw/ResourceUtils.h b/libs/androidfw/include/androidfw/ResourceUtils.h
new file mode 100644
index 0000000..6bf7c24
--- /dev/null
+++ b/libs/androidfw/include/androidfw/ResourceUtils.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROIDFW_RESOURCEUTILS_H
+#define ANDROIDFW_RESOURCEUTILS_H
+
+#include "androidfw/StringPiece.h"
+
+namespace android {
+
+// Extracts the package, type, and name from a string of the format: [[package:]type/]name
+// Validation must be performed on each extracted piece.
+// Returns false if there was a syntax error.
+bool ExtractResourceName(const StringPiece& str, StringPiece* out_package, StringPiece* out_type,
+ StringPiece* out_entry);
+
+inline uint32_t fix_package_id(uint32_t resid, uint8_t package_id) {
+ return resid | (static_cast<uint32_t>(package_id) << 24);
+}
+
+inline uint8_t get_package_id(uint32_t resid) {
+ return static_cast<uint8_t>((resid >> 24) & 0x000000ffu);
+}
+
+// The type ID is 1-based, so if the returned value is 0 it is invalid.
+inline uint8_t get_type_id(uint32_t resid) {
+ return static_cast<uint8_t>((resid >> 16) & 0x000000ffu);
+}
+
+inline uint16_t get_entry_id(uint32_t resid) { return static_cast<uint16_t>(resid & 0x0000ffffu); }
+
+inline bool is_internal_resid(uint32_t resid) {
+ return (resid & 0xffff0000u) != 0 && (resid & 0x00ff0000u) == 0;
+}
+
+inline bool is_valid_resid(uint32_t resid) {
+ return (resid & 0x00ff0000u) != 0 && (resid & 0xff000000u) != 0;
+}
+
+inline uint32_t make_resid(uint8_t package_id, uint8_t type_id, uint16_t entry_id) {
+ return (static_cast<uint32_t>(package_id) << 24) | (static_cast<uint32_t>(type_id) << 16) |
+ entry_id;
+}
+
+} // namespace android
+
+#endif /* ANDROIDFW_RESOURCEUTILS_H */
diff --git a/libs/androidfw/include/androidfw/StringPiece.h b/libs/androidfw/include/androidfw/StringPiece.h
index c9effd1..8f6824b 100644
--- a/libs/androidfw/include/androidfw/StringPiece.h
+++ b/libs/androidfw/include/androidfw/StringPiece.h
@@ -257,6 +257,16 @@
return data_ + length_;
}
+template <typename TChar>
+inline bool operator==(const TChar* lhs, const BasicStringPiece<TChar>& rhs) {
+ return BasicStringPiece<TChar>(lhs) == rhs;
+}
+
+template <typename TChar>
+inline bool operator!=(const TChar* lhs, const BasicStringPiece<TChar>& rhs) {
+ return BasicStringPiece<TChar>(lhs) != rhs;
+}
+
inline ::std::ostream& operator<<(::std::ostream& out, const BasicStringPiece<char>& str) {
return out.write(str.data(), str.size());
}
diff --git a/libs/androidfw/include/androidfw/Util.h b/libs/androidfw/include/androidfw/Util.h
index 96b42bf..3950cf2 100644
--- a/libs/androidfw/include/androidfw/Util.h
+++ b/libs/androidfw/include/androidfw/Util.h
@@ -106,29 +106,6 @@
pointer ptr_;
};
-inline uint32_t fix_package_id(uint32_t resid, uint8_t package_id) {
- return resid | (static_cast<uint32_t>(package_id) << 24);
-}
-
-inline uint8_t get_package_id(uint32_t resid) {
- return static_cast<uint8_t>((resid >> 24) & 0x000000ffu);
-}
-
-// The type ID is 1-based, so if the returned value is 0 it is invalid.
-inline uint8_t get_type_id(uint32_t resid) {
- return static_cast<uint8_t>((resid >> 16) & 0x000000ffu);
-}
-
-inline uint16_t get_entry_id(uint32_t resid) { return static_cast<uint16_t>(resid & 0x0000ffffu); }
-
-inline bool is_internal_resid(uint32_t resid) {
- return (resid & 0xffff0000u) != 0 && (resid & 0x00ff0000u) == 0;
-}
-
-inline bool is_valid_resid(uint32_t resid) {
- return (resid & 0x00ff0000u) != 0 && (resid & 0xff000000u) != 0;
-}
-
void ReadUtf16StringFromDevice(const uint16_t* src, size_t len, std::string* out);
} // namespace util
diff --git a/libs/androidfw/tests/Android.mk b/libs/androidfw/tests/Android.mk
index 650f813..19527c5 100644
--- a/libs/androidfw/tests/Android.mk
+++ b/libs/androidfw/tests/Android.mk
@@ -32,6 +32,7 @@
ConfigLocale_test.cpp \
Idmap_test.cpp \
LoadedArsc_test.cpp \
+ ResourceUtils_test.cpp \
ResTable_test.cpp \
Split_test.cpp \
StringPiece_test.cpp \
diff --git a/libs/androidfw/tests/AssetManager2_test.cpp b/libs/androidfw/tests/AssetManager2_test.cpp
index 557d8d4..78fbb0f 100644
--- a/libs/androidfw/tests/AssetManager2_test.cpp
+++ b/libs/androidfw/tests/AssetManager2_test.cpp
@@ -20,6 +20,7 @@
#include "android-base/logging.h"
#include "TestHelpers.h"
+#include "androidfw/ResourceUtils.h"
#include "data/appaslib/R.h"
#include "data/basic/R.h"
#include "data/lib_one/R.h"
@@ -194,11 +195,11 @@
ResTable_config selected_config;
uint32_t flags;
ApkAssetsCookie cookie = assetmanager.GetResource(
- util::fix_package_id(appaslib::R::integer::number1, 0x02), false /*may_be_bag*/,
+ fix_package_id(appaslib::R::integer::number1, 0x02), false /*may_be_bag*/,
0u /*density_override*/, &value, &selected_config, &flags);
ASSERT_NE(kInvalidCookie, cookie);
EXPECT_EQ(Res_value::TYPE_REFERENCE, value.dataType);
- EXPECT_EQ(util::fix_package_id(appaslib::R::array::integerArray1, 0x02), value.data);
+ EXPECT_EQ(fix_package_id(appaslib::R::array::integerArray1, 0x02), value.data);
}
TEST_F(AssetManager2Test, FindsBagResourceFromSingleApkAssets) {
@@ -238,9 +239,9 @@
// First two attributes come from lib_one.
EXPECT_EQ(1, bag->entries[0].cookie);
- EXPECT_EQ(0x03, util::get_package_id(bag->entries[0].key));
+ EXPECT_EQ(0x03, get_package_id(bag->entries[0].key));
EXPECT_EQ(1, bag->entries[1].cookie);
- EXPECT_EQ(0x03, util::get_package_id(bag->entries[1].key));
+ EXPECT_EQ(0x03, get_package_id(bag->entries[1].key));
}
TEST_F(AssetManager2Test, MergesStylesWithParentFromSingleApkAssets) {
diff --git a/libs/androidfw/tests/ResourceUtils_test.cpp b/libs/androidfw/tests/ResourceUtils_test.cpp
new file mode 100644
index 0000000..b64a884
--- /dev/null
+++ b/libs/androidfw/tests/ResourceUtils_test.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "androidfw/ResourceUtils.h"
+
+#include "TestHelpers.h"
+
+namespace android {
+
+TEST(ResourceUtilsTest, ExtractResourceName) {
+ StringPiece package, type, entry;
+ ASSERT_TRUE(ExtractResourceName("android:string/foo", &package, &type, &entry));
+ EXPECT_EQ("android", package);
+ EXPECT_EQ("string", type);
+ EXPECT_EQ("foo", entry);
+
+ ASSERT_TRUE(ExtractResourceName("string/foo", &package, &type, &entry));
+ EXPECT_EQ("", package);
+ EXPECT_EQ("string", type);
+ EXPECT_EQ("foo", entry);
+
+ ASSERT_TRUE(ExtractResourceName("foo", &package, &type, &entry));
+ EXPECT_EQ("", package);
+ EXPECT_EQ("", type);
+ EXPECT_EQ("foo", entry);
+
+ ASSERT_TRUE(ExtractResourceName("android:foo", &package, &type, &entry));
+ EXPECT_EQ("android", package);
+ EXPECT_EQ("", type);
+ EXPECT_EQ("foo", entry);
+
+ EXPECT_FALSE(ExtractResourceName(":string/foo", &package, &type, &entry));
+ EXPECT_FALSE(ExtractResourceName("/foo", &package, &type, &entry));
+}
+
+} // namespace android
diff --git a/libs/androidfw/tests/Theme_test.cpp b/libs/androidfw/tests/Theme_test.cpp
index daed28b0..dfff9c0 100644
--- a/libs/androidfw/tests/Theme_test.cpp
+++ b/libs/androidfw/tests/Theme_test.cpp
@@ -19,6 +19,7 @@
#include "android-base/logging.h"
#include "TestHelpers.h"
+#include "androidfw/ResourceUtils.h"
#include "data/lib_one/R.h"
#include "data/libclient/R.h"
#include "data/styles/R.h"
@@ -215,9 +216,9 @@
EXPECT_EQ(Res_value::TYPE_REFERENCE, value.dataType);
// lib_one is assigned package ID 0x03.
- EXPECT_EQ(3u, util::get_package_id(value.data));
- EXPECT_EQ(util::get_type_id(lib_one::R::string::foo), util::get_type_id(value.data));
- EXPECT_EQ(util::get_entry_id(lib_one::R::string::foo), util::get_entry_id(value.data));
+ EXPECT_EQ(3u, get_package_id(value.data));
+ EXPECT_EQ(get_type_id(lib_one::R::string::foo), get_type_id(value.data));
+ EXPECT_EQ(get_entry_id(lib_one::R::string::foo), get_entry_id(value.data));
}
TEST_F(ThemeTest, CopyThemeSameAssetManager) {
diff --git a/tools/aapt2/ResourceUtils.cpp b/tools/aapt2/ResourceUtils.cpp
index 1123967..150dc58 100644
--- a/tools/aapt2/ResourceUtils.cpp
+++ b/tools/aapt2/ResourceUtils.cpp
@@ -19,6 +19,7 @@
#include <sstream>
#include "androidfw/ResourceTypes.h"
+#include "androidfw/ResourceUtils.h"
#include "NameMangler.h"
#include "SdkConstants.h"
@@ -69,31 +70,6 @@
return name_out;
}
-bool ExtractResourceName(const StringPiece& str, StringPiece* out_package,
- StringPiece* out_type, StringPiece* out_entry) {
- bool has_package_separator = false;
- bool has_type_separator = false;
- const char* start = str.data();
- const char* end = start + str.size();
- const char* current = start;
- while (current != end) {
- if (out_type->size() == 0 && *current == '/') {
- has_type_separator = true;
- out_type->assign(start, current - start);
- start = current + 1;
- } else if (out_package->size() == 0 && *current == ':') {
- has_package_separator = true;
- out_package->assign(start, current - start);
- start = current + 1;
- }
- current++;
- }
- out_entry->assign(start, end - start);
-
- return !(has_package_separator && out_package->empty()) &&
- !(has_type_separator && out_type->empty());
-}
-
bool ParseResourceName(const StringPiece& str, ResourceNameRef* out_ref,
bool* out_private) {
if (str.empty()) {
@@ -110,8 +86,8 @@
StringPiece package;
StringPiece type;
StringPiece entry;
- if (!ExtractResourceName(str.substr(offset, str.size() - offset), &package,
- &type, &entry)) {
+ if (!android::ExtractResourceName(str.substr(offset, str.size() - offset), &package, &type,
+ &entry)) {
return false;
}
@@ -197,8 +173,8 @@
StringPiece package;
StringPiece type;
StringPiece entry;
- if (!ExtractResourceName(trimmed_str.substr(1, trimmed_str.size() - 1),
- &package, &type, &entry)) {
+ if (!android::ExtractResourceName(trimmed_str.substr(1, trimmed_str.size() - 1), &package,
+ &type, &entry)) {
return false;
}
@@ -258,7 +234,7 @@
ref.type = ResourceType::kStyle;
StringPiece type_str;
- ExtractResourceName(name, &ref.package, &type_str, &ref.entry);
+ android::ExtractResourceName(name, &ref.package, &type_str, &ref.entry);
if (!type_str.empty()) {
// If we have a type, make sure it is a Style.
const ResourceType* parsed_type = ParseResourceType(type_str);
diff --git a/tools/aapt2/ResourceUtils.h b/tools/aapt2/ResourceUtils.h
index bd3a8e3..59b78f4 100644
--- a/tools/aapt2/ResourceUtils.h
+++ b/tools/aapt2/ResourceUtils.h
@@ -29,18 +29,6 @@
namespace aapt {
namespace ResourceUtils {
-/*
- * Extracts the package, type, and name from a string of the format:
- *
- * [package:]type/name
- *
- * where the package can be empty. Validation must be performed on each
- * individual extracted piece to verify that the pieces are valid.
- * Returns false if there was no package but a ':' was present.
- */
-bool ExtractResourceName(const android::StringPiece& str, android::StringPiece* out_package,
- android::StringPiece* out_type, android::StringPiece* out_entry);
-
/**
* Returns true if the string was parsed as a resource name
* ([*][package:]type/name), with