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