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