diff options
author | 2017-02-16 12:05:42 -0800 | |
---|---|---|
committer | 2017-02-22 11:16:13 -0800 | |
commit | ceb9b2f80f853059233cdd29057f39a5960a74ae (patch) | |
tree | 9093e8537319a97d8a2cbd8d4f0042c81de5ff8e /tools/aapt2/process | |
parent | f9bd2944694539f1dce74d420156cc50bbb4af14 (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.cpp | 104 | ||||
-rw-r--r-- | tools/aapt2/process/SymbolTable.h | 27 | ||||
-rw-r--r-- | tools/aapt2/process/SymbolTable_test.cpp | 15 |
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 |