1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef AAPT_PROCESS_SYMBOLTABLE_H 18 #define AAPT_PROCESS_SYMBOLTABLE_H 19 20 #include <algorithm> 21 #include <memory> 22 #include <vector> 23 24 #include "android-base/macros.h" 25 #include "androidfw/Asset.h" 26 #include "androidfw/AssetManager2.h" 27 #include "utils/JenkinsHash.h" 28 #include "utils/LruCache.h" 29 30 #include "Resource.h" 31 #include "ResourceTable.h" 32 #include "ResourceValues.h" 33 #include "util/Util.h" 34 35 namespace aapt { 36 37 inline android::hash_t hash_type(const ResourceName& name) { 38 std::hash<std::string> str_hash; 39 android::hash_t hash = 0; 40 hash = android::JenkinsHashMix(hash, (uint32_t)str_hash(name.package)); 41 hash = android::JenkinsHashMix(hash, (uint32_t)name.type); 42 hash = android::JenkinsHashMix(hash, (uint32_t)str_hash(name.entry)); 43 return hash; 44 } 45 46 inline android::hash_t hash_type(const ResourceId& id) { 47 return android::hash_type(id.id); 48 } 49 50 class ISymbolSource; 51 class ISymbolTableDelegate; 52 class NameMangler; 53 54 class SymbolTable { 55 public: 56 struct Symbol { 57 Symbol() = default; 58 59 explicit Symbol(const Maybe<ResourceId>& i, const std::shared_ptr<Attribute>& attr = {}, 60 bool pub = false) 61 : id(i), attribute(attr), is_public(pub) { 62 } 63 64 Symbol(const Symbol&) = default; 65 Symbol(Symbol&&) = default; 66 Symbol& operator=(const Symbol&) = default; 67 Symbol& operator=(Symbol&&) = default; 68 69 Maybe<ResourceId> id; 70 std::shared_ptr<Attribute> attribute; 71 bool is_public = false; 72 bool is_dynamic = false; 73 }; 74 75 explicit SymbolTable(NameMangler* mangler); 76 77 // Overrides the default ISymbolTableDelegate, which allows a custom defined strategy for 78 // looking up resources from a set of sources. 79 void SetDelegate(std::unique_ptr<ISymbolTableDelegate> delegate); 80 81 // Appends a symbol source. The cache is not cleared since entries that 82 // have already been found would take precedence due to ordering. 83 void AppendSource(std::unique_ptr<ISymbolSource> source); 84 85 // Prepends a symbol source so that its symbols take precedence. This will 86 // cause the existing cache to be cleared. 87 void PrependSource(std::unique_ptr<ISymbolSource> source); 88 89 // NOTE: Never hold on to the result between calls to FindByXXX. The 90 // results are stored in a cache which may evict entries on subsequent calls. 91 const Symbol* FindByName(const ResourceName& name); 92 93 // NOTE: Never hold on to the result between calls to FindByXXX. The 94 // results are stored in a cache which may evict entries on subsequent calls. 95 const Symbol* FindById(const ResourceId& id); 96 97 // Let's the ISymbolSource decide whether looking up by name or ID is faster, 98 // if both are available. 99 // NOTE: Never hold on to the result between calls to FindByXXX. The 100 // results are stored in a cache which may evict entries on subsequent calls. 101 const Symbol* FindByReference(const Reference& ref); 102 103 private: 104 NameMangler* mangler_; 105 std::unique_ptr<ISymbolTableDelegate> delegate_; 106 std::vector<std::unique_ptr<ISymbolSource>> sources_; 107 108 // We use shared_ptr because unique_ptr is not supported and 109 // we need automatic deletion. 110 android::LruCache<ResourceName, std::shared_ptr<Symbol>> cache_; 111 android::LruCache<ResourceId, std::shared_ptr<Symbol>> id_cache_; 112 113 DISALLOW_COPY_AND_ASSIGN(SymbolTable); 114 }; 115 116 // Allows the customization of the lookup strategy/order of a symbol from a set of 117 // symbol sources. 118 class ISymbolTableDelegate { 119 public: 120 ISymbolTableDelegate() = default; 121 virtual ~ISymbolTableDelegate() = default; 122 123 // The name is already mangled and does not need further processing. 124 virtual std::unique_ptr<SymbolTable::Symbol> FindByName( 125 const ResourceName& name, const std::vector<std::unique_ptr<ISymbolSource>>& sources) = 0; 126 127 virtual std::unique_ptr<SymbolTable::Symbol> FindById( 128 ResourceId id, const std::vector<std::unique_ptr<ISymbolSource>>& sources) = 0; 129 130 private: 131 DISALLOW_COPY_AND_ASSIGN(ISymbolTableDelegate); 132 }; 133 134 class DefaultSymbolTableDelegate : public ISymbolTableDelegate { 135 public: 136 DefaultSymbolTableDelegate() = default; 137 virtual ~DefaultSymbolTableDelegate() = default; 138 139 virtual std::unique_ptr<SymbolTable::Symbol> FindByName( 140 const ResourceName& name, 141 const std::vector<std::unique_ptr<ISymbolSource>>& sources) override; 142 virtual std::unique_ptr<SymbolTable::Symbol> FindById( 143 ResourceId id, const std::vector<std::unique_ptr<ISymbolSource>>& sources) override; 144 145 private: 146 DISALLOW_COPY_AND_ASSIGN(DefaultSymbolTableDelegate); 147 }; 148 149 // An interface that a symbol source implements in order to surface symbol information 150 // to the symbol table. 151 class ISymbolSource { 152 public: 153 virtual ~ISymbolSource() = default; 154 155 virtual std::unique_ptr<SymbolTable::Symbol> FindByName( 156 const ResourceName& name) = 0; 157 virtual std::unique_ptr<SymbolTable::Symbol> FindById(ResourceId id) = 0; 158 159 // Default implementation tries the name if it exists, else the ID. 160 virtual std::unique_ptr<SymbolTable::Symbol> FindByReference( 161 const Reference& ref) { 162 if (ref.name) { 163 return FindByName(ref.name.value()); 164 } else if (ref.id) { 165 return FindById(ref.id.value()); 166 } 167 return {}; 168 } 169 }; 170 171 // Exposes the resources in a ResourceTable as symbols for SymbolTable. 172 // Instances of this class must outlive the encompassed ResourceTable. 173 // Lookups by ID are ignored. 174 class ResourceTableSymbolSource : public ISymbolSource { 175 public: 176 explicit ResourceTableSymbolSource(ResourceTable* table) : table_(table) {} 177 178 std::unique_ptr<SymbolTable::Symbol> FindByName( 179 const ResourceName& name) override; 180 181 std::unique_ptr<SymbolTable::Symbol> FindById(ResourceId id) override { 182 return {}; 183 } 184 185 private: 186 ResourceTable* table_; 187 188 DISALLOW_COPY_AND_ASSIGN(ResourceTableSymbolSource); 189 }; 190 191 class AssetManagerSymbolSource : public ISymbolSource { 192 public: 193 AssetManagerSymbolSource() = default; 194 195 bool AddAssetPath(const android::StringPiece& path); 196 std::map<size_t, std::string> GetAssignedPackageIds() const; 197 bool IsPackageDynamic(uint32_t packageId) const; 198 199 std::unique_ptr<SymbolTable::Symbol> FindByName( 200 const ResourceName& name) override; 201 std::unique_ptr<SymbolTable::Symbol> FindById(ResourceId id) override; 202 std::unique_ptr<SymbolTable::Symbol> FindByReference( 203 const Reference& ref) override; 204 205 android::AssetManager2* GetAssetManager() { 206 return &asset_manager_; 207 } 208 209 private: 210 android::AssetManager2 asset_manager_; 211 std::vector<std::unique_ptr<const android::ApkAssets>> apk_assets_; 212 213 DISALLOW_COPY_AND_ASSIGN(AssetManagerSymbolSource); 214 }; 215 216 } // namespace aapt 217 218 #endif /* AAPT_PROCESS_SYMBOLTABLE_H */ 219