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