summaryrefslogtreecommitdiff
path: root/tools/aapt2/process
diff options
context:
space:
mode:
author Adam Lesinski <adamlesinski@google.com> 2017-02-16 12:05:42 -0800
committer Adam Lesinski <adamlesinski@google.com> 2017-02-22 11:16:13 -0800
commitceb9b2f80f853059233cdd29057f39a5960a74ae (patch)
tree9093e8537319a97d8a2cbd8d4f0042c81de5ff8e /tools/aapt2/process
parentf9bd2944694539f1dce74d420156cc50bbb4af14 (diff)
AAPT2: Shared library support
Test: make aapt2_tests Change-Id: I98dddf1367e6c0ac425bb20be46e6ff05f4f2f45
Diffstat (limited to 'tools/aapt2/process')
-rw-r--r--tools/aapt2/process/SymbolTable.cpp104
-rw-r--r--tools/aapt2/process/SymbolTable.h27
-rw-r--r--tools/aapt2/process/SymbolTable_test.cpp15
3 files changed, 99 insertions, 47 deletions
diff --git a/tools/aapt2/process/SymbolTable.cpp b/tools/aapt2/process/SymbolTable.cpp
index 1a3da73b8ce0..5d75e76af035 100644
--- a/tools/aapt2/process/SymbolTable.cpp
+++ b/tools/aapt2/process/SymbolTable.cpp
@@ -16,10 +16,15 @@
#include "process/SymbolTable.h"
+#include <iostream>
+
+#include "android-base/logging.h"
+#include "android-base/stringprintf.h"
#include "androidfw/AssetManager.h"
#include "androidfw/ResourceTypes.h"
#include "ConfigDescription.h"
+#include "NameMangler.h"
#include "Resource.h"
#include "ResourceUtils.h"
#include "ValueVisitor.h"
@@ -45,25 +50,49 @@ void SymbolTable::PrependSource(std::unique_ptr<ISymbolSource> source) {
}
const SymbolTable::Symbol* SymbolTable::FindByName(const ResourceName& name) {
- if (const std::shared_ptr<Symbol>& s = cache_.get(name)) {
+ const ResourceName* name_with_package = &name;
+
+ // Fill in the package name if necessary.
+ // If there is no package in `name`, we will need to copy the ResourceName
+ // and store it somewhere; we use the Maybe<> class to reserve storage.
+ Maybe<ResourceName> name_with_package_impl;
+ if (name.package.empty()) {
+ name_with_package_impl = ResourceName(mangler_->GetTargetPackageName(), name.type, name.entry);
+ name_with_package = &name_with_package_impl.value();
+ }
+
+ // We store the name unmangled in the cache, so look it up as-is.
+ if (const std::shared_ptr<Symbol>& s = cache_.get(*name_with_package)) {
return s.get();
}
- // We did not find it in the cache, so look through the sources.
+ // The name was not found in the cache. Mangle it (if necessary) and find it in our sources.
+ // Again, here we use a Maybe<> object to reserve storage if we need to mangle.
+ const ResourceName* mangled_name = name_with_package;
+ Maybe<ResourceName> mangled_name_impl;
+ if (mangler_->ShouldMangle(name_with_package->package)) {
+ mangled_name_impl = mangler_->MangleName(*name_with_package);
+ mangled_name = &mangled_name_impl.value();
+ }
+
for (auto& symbolSource : sources_) {
- std::unique_ptr<Symbol> symbol = symbolSource->FindByName(name);
+ std::unique_ptr<Symbol> symbol = symbolSource->FindByName(*mangled_name);
if (symbol) {
// Take ownership of the symbol into a shared_ptr. We do this because
- // LruCache
- // doesn't support unique_ptr.
- std::shared_ptr<Symbol> shared_symbol =
- std::shared_ptr<Symbol>(symbol.release());
- cache_.put(name, shared_symbol);
+ // LruCache doesn't support unique_ptr.
+ std::shared_ptr<Symbol> shared_symbol(std::move(symbol));
+
+ // Since we look in the cache with the unmangled, but package prefixed
+ // name, we must put the same name into the cache.
+ cache_.put(*name_with_package, shared_symbol);
if (shared_symbol->id) {
// The symbol has an ID, so we can also cache this!
id_cache_.put(shared_symbol->id.value(), shared_symbol);
}
+
+ // Returns the raw pointer. Callers are not expected to hold on to this
+ // between calls to Find*.
return shared_symbol.get();
}
}
@@ -79,12 +108,13 @@ const SymbolTable::Symbol* SymbolTable::FindById(const ResourceId& id) {
for (auto& symbolSource : sources_) {
std::unique_ptr<Symbol> symbol = symbolSource->FindById(id);
if (symbol) {
- // Take ownership of the symbol into a shared_ptr. We do this because
- // LruCache
+ // Take ownership of the symbol into a shared_ptr. We do this because LruCache
// doesn't support unique_ptr.
- std::shared_ptr<Symbol> shared_symbol =
- std::shared_ptr<Symbol>(symbol.release());
+ std::shared_ptr<Symbol> shared_symbol(std::move(symbol));
id_cache_.put(id, shared_symbol);
+
+ // Returns the raw pointer. Callers are not expected to hold on to this
+ // between calls to Find*.
return shared_symbol.get();
}
}
@@ -92,16 +122,12 @@ const SymbolTable::Symbol* SymbolTable::FindById(const ResourceId& id) {
}
const SymbolTable::Symbol* SymbolTable::FindByReference(const Reference& ref) {
- // First try the ID. This is because when we lookup by ID, we only fill in the
- // ID cache.
- // Looking up by name fills in the name and ID cache. So a cache miss will
- // cause a failed
- // ID lookup, then a successful name lookup. Subsequent look ups will hit
- // immediately
+ // First try the ID. This is because when we lookup by ID, we only fill in the ID cache.
+ // Looking up by name fills in the name and ID cache. So a cache miss will cause a failed
+ // ID lookup, then a successful name lookup. Subsequent look ups will hit immediately
// because the ID is cached too.
//
- // If we looked up by name first, a cache miss would mean we failed to lookup
- // by name, then
+ // If we looked up by name first, a cache miss would mean we failed to lookup by name, then
// succeeded to lookup by ID. Subsequent lookups will miss then hit.
const SymbolTable::Symbol* symbol = nullptr;
if (ref.id) {
@@ -120,25 +146,21 @@ std::unique_ptr<SymbolTable::Symbol> ResourceTableSymbolSource::FindByName(
if (!result) {
if (name.type == ResourceType::kAttr) {
// Recurse and try looking up a private attribute.
- return FindByName(
- ResourceName(name.package, ResourceType::kAttrPrivate, name.entry));
+ return FindByName(ResourceName(name.package, ResourceType::kAttrPrivate, name.entry));
}
return {};
}
ResourceTable::SearchResult sr = result.value();
- std::unique_ptr<SymbolTable::Symbol> symbol =
- util::make_unique<SymbolTable::Symbol>();
+ std::unique_ptr<SymbolTable::Symbol> symbol = util::make_unique<SymbolTable::Symbol>();
symbol->is_public = (sr.entry->symbol_status.state == SymbolState::kPublic);
if (sr.package->id && sr.type->id && sr.entry->id) {
- symbol->id = ResourceId(sr.package->id.value(), sr.type->id.value(),
- sr.entry->id.value());
+ symbol->id = ResourceId(sr.package->id.value(), sr.type->id.value(), sr.entry->id.value());
}
- if (name.type == ResourceType::kAttr ||
- name.type == ResourceType::kAttrPrivate) {
+ if (name.type == ResourceType::kAttr || name.type == ResourceType::kAttrPrivate) {
const ConfigDescription kDefaultConfig;
ResourceConfigValue* config_value = sr.entry->FindValue(kDefaultConfig);
if (config_value) {
@@ -155,8 +177,18 @@ std::unique_ptr<SymbolTable::Symbol> ResourceTableSymbolSource::FindByName(
bool AssetManagerSymbolSource::AddAssetPath(const StringPiece& path) {
int32_t cookie = 0;
- return assets_.addAssetPath(android::String8(path.data(), path.size()),
- &cookie);
+ return assets_.addAssetPath(android::String8(path.data(), path.size()), &cookie);
+}
+
+std::map<size_t, std::string> AssetManagerSymbolSource::GetAssignedPackageIds() const {
+ std::map<size_t, std::string> package_map;
+ const android::ResTable& table = assets_.getResources(false);
+ const size_t package_count = table.getBasePackageCount();
+ for (size_t i = 0; i < package_count; i++) {
+ package_map[table.getBasePackageId(i)] =
+ util::Utf16ToUtf8(android::StringPiece16(table.getBasePackageName(i).string()));
+ }
+ return package_map;
}
static std::unique_ptr<SymbolTable::Symbol> LookupAttributeInTable(
@@ -170,8 +202,7 @@ static std::unique_ptr<SymbolTable::Symbol> LookupAttributeInTable(
}
// We found a resource.
- std::unique_ptr<SymbolTable::Symbol> s =
- util::make_unique<SymbolTable::Symbol>();
+ std::unique_ptr<SymbolTable::Symbol> s = util::make_unique<SymbolTable::Symbol>();
s->id = id;
// Check to see if it is an attribute.
@@ -204,8 +235,7 @@ static std::unique_ptr<SymbolTable::Symbol> LookupAttributeInTable(
return nullptr;
}
- Maybe<ResourceName> parsed_name =
- ResourceUtils::ToResourceName(entry_name);
+ Maybe<ResourceName> parsed_name = ResourceUtils::ToResourceName(entry_name);
if (!parsed_name) {
return nullptr;
}
@@ -246,8 +276,7 @@ std::unique_ptr<SymbolTable::Symbol> AssetManagerSymbolSource::FindByName(
}
if (s) {
- s->is_public =
- (type_spec_flags & android::ResTable_typeSpec::SPEC_PUBLIC) != 0;
+ s->is_public = (type_spec_flags & android::ResTable_typeSpec::SPEC_PUBLIC) != 0;
return s;
}
return {};
@@ -282,8 +311,7 @@ std::unique_ptr<SymbolTable::Symbol> AssetManagerSymbolSource::FindById(
}
if (s) {
- s->is_public =
- (type_spec_flags & android::ResTable_typeSpec::SPEC_PUBLIC) != 0;
+ s->is_public = (type_spec_flags & android::ResTable_typeSpec::SPEC_PUBLIC) != 0;
return s;
}
return {};
diff --git a/tools/aapt2/process/SymbolTable.h b/tools/aapt2/process/SymbolTable.h
index cf597bb4e679..298da4d42c77 100644
--- a/tools/aapt2/process/SymbolTable.h
+++ b/tools/aapt2/process/SymbolTable.h
@@ -47,6 +47,7 @@ inline android::hash_t hash_type(const ResourceId& id) {
}
class ISymbolSource;
+class NameMangler;
class SymbolTable {
public:
@@ -72,25 +73,32 @@ class SymbolTable {
bool is_public = false;
};
- SymbolTable() : cache_(200), id_cache_(200) {}
+ SymbolTable(NameMangler* mangler) : mangler_(mangler), cache_(200), id_cache_(200) {}
+ // Appends a symbol source. The cache is not cleared since entries that
+ // have already been found would take precedence due to ordering.
void AppendSource(std::unique_ptr<ISymbolSource> source);
+
+ // Prepends a symbol source so that its symbols take precedence. This will
+ // cause the existing cache to be cleared.
void PrependSource(std::unique_ptr<ISymbolSource> source);
- /**
- * Never hold on to the result between calls to FindByName or FindById. The
- * results stored in a cache which may evict entries.
- */
+ // NOTE: Never hold on to the result between calls to FindByXXX. The
+ // results are stored in a cache which may evict entries on subsequent calls.
const Symbol* FindByName(const ResourceName& name);
+
+ // NOTE: Never hold on to the result between calls to FindByXXX. The
+ // results are stored in a cache which may evict entries on subsequent calls.
const Symbol* FindById(const ResourceId& id);
- /**
- * Let's the ISymbolSource decide whether looking up by name or ID is faster,
- * if both are available.
- */
+ // Let's the ISymbolSource decide whether looking up by name or ID is faster,
+ // if both are available.
+ // NOTE: Never hold on to the result between calls to FindByXXX. The
+ // results are stored in a cache which may evict entries on subsequent calls.
const Symbol* FindByReference(const Reference& ref);
private:
+ NameMangler* mangler_;
std::vector<std::unique_ptr<ISymbolSource>> sources_;
// We use shared_ptr because unique_ptr is not supported and
@@ -155,6 +163,7 @@ class AssetManagerSymbolSource : public ISymbolSource {
AssetManagerSymbolSource() = default;
bool AddAssetPath(const android::StringPiece& path);
+ std::map<size_t, std::string> GetAssignedPackageIds() const;
std::unique_ptr<SymbolTable::Symbol> FindByName(
const ResourceName& name) override;
diff --git a/tools/aapt2/process/SymbolTable_test.cpp b/tools/aapt2/process/SymbolTable_test.cpp
index 9ea0786cbc8e..bba316f4b484 100644
--- a/tools/aapt2/process/SymbolTable_test.cpp
+++ b/tools/aapt2/process/SymbolTable_test.cpp
@@ -55,4 +55,19 @@ TEST(ResourceTableSymbolSourceTest, FindPrivateAttrSymbol) {
EXPECT_NE(nullptr, s->attribute);
}
+TEST(SymbolTableTest, FindByName) {
+ std::unique_ptr<ResourceTable> table =
+ test::ResourceTableBuilder()
+ .AddSimple("com.android.app:id/foo")
+ .AddSimple("com.android.app:id/" + NameMangler::MangleEntry("com.android.lib", "foo"))
+ .Build();
+
+ NameMangler mangler(NameManglerPolicy{"com.android.app", {"com.android.lib"}});
+ SymbolTable symbol_table(&mangler);
+ symbol_table.AppendSource(util::make_unique<ResourceTableSymbolSource>(table.get()));
+
+ EXPECT_NE(nullptr, symbol_table.FindByName(test::ParseNameOrDie("id/foo")));
+ EXPECT_NE(nullptr, symbol_table.FindByName(test::ParseNameOrDie("com.android.lib:id/foo")));
+}
+
} // namespace aapt