• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "Resource.h"
21 #include "ResourceTable.h"
22 #include "ResourceValues.h"
23 #include "util/Util.h"
24 
25 #include <utils/JenkinsHash.h>
26 #include <utils/LruCache.h>
27 
28 #include <android-base/macros.h>
29 #include <androidfw/AssetManager.h>
30 #include <algorithm>
31 #include <memory>
32 #include <vector>
33 
34 namespace aapt {
35 
hash_type(const ResourceName & name)36 inline android::hash_t hash_type(const ResourceName& name) {
37     std::hash<std::u16string> strHash;
38     android::hash_t hash = 0;
39     hash = android::JenkinsHashMix(hash, (uint32_t) strHash(name.package));
40     hash = android::JenkinsHashMix(hash, (uint32_t) name.type);
41     hash = android::JenkinsHashMix(hash, (uint32_t) strHash(name.entry));
42     return hash;
43 }
44 
hash_type(const ResourceId & id)45 inline android::hash_t hash_type(const ResourceId& id) {
46     return android::hash_type(id.id);
47 }
48 
49 class ISymbolSource;
50 
51 class SymbolTable {
52 public:
53     struct Symbol {
SymbolSymbol54         Symbol() : Symbol(Maybe<ResourceId>{}) {
55         }
56 
SymbolSymbol57         Symbol(const Maybe<ResourceId>& i) : Symbol(i, nullptr) {
58         }
59 
SymbolSymbol60         Symbol(const Maybe<ResourceId>& i, const std::shared_ptr<Attribute>& attr) :
61                 Symbol(i, attr, false) {
62         }
63 
SymbolSymbol64         Symbol(const Maybe<ResourceId>& i, const std::shared_ptr<Attribute>& attr, bool pub) :
65                 id(i), attribute(attr), isPublic(pub) {
66         }
67 
68         Symbol(const Symbol&) = default;
69         Symbol(Symbol&&) = default;
70         Symbol& operator=(const Symbol&) = default;
71         Symbol& operator=(Symbol&&) = default;
72 
73         Maybe<ResourceId> id;
74         std::shared_ptr<Attribute> attribute;
75         bool isPublic = false;
76     };
77 
SymbolTable()78     SymbolTable() : mCache(200), mIdCache(200) {
79     }
80 
81     void appendSource(std::unique_ptr<ISymbolSource> source);
82     void prependSource(std::unique_ptr<ISymbolSource> source);
83 
84     /**
85      * Never hold on to the result between calls to findByName or findById. The results
86      * are typically stored in a cache which may evict entries.
87      */
88     const Symbol* findByName(const ResourceName& name);
89     const Symbol* findById(ResourceId id);
90 
91     /**
92      * Let's the ISymbolSource decide whether looking up by name or ID is faster, if both
93      * are available.
94      */
95     const Symbol* findByReference(const Reference& ref);
96 
97 private:
98     std::vector<std::unique_ptr<ISymbolSource>> mSources;
99 
100     // We use shared_ptr because unique_ptr is not supported and
101     // we need automatic deletion.
102     android::LruCache<ResourceName, std::shared_ptr<Symbol>> mCache;
103     android::LruCache<ResourceId, std::shared_ptr<Symbol>> mIdCache;
104 
105     DISALLOW_COPY_AND_ASSIGN(SymbolTable);
106 };
107 
108 /**
109  * An interface that a symbol source implements in order to surface symbol information
110  * to the symbol table.
111  */
112 class ISymbolSource {
113 public:
114     virtual ~ISymbolSource() = default;
115 
116     virtual std::unique_ptr<SymbolTable::Symbol> findByName(const ResourceName& name) = 0;
117     virtual std::unique_ptr<SymbolTable::Symbol> findById(ResourceId id) = 0;
118 
119     /**
120      * Default implementation tries the name if it exists, else the ID.
121      */
findByReference(const Reference & ref)122     virtual std::unique_ptr<SymbolTable::Symbol> findByReference(const Reference& ref) {
123         if (ref.name) {
124             return findByName(ref.name.value());
125         } else if (ref.id) {
126             return findById(ref.id.value());
127         }
128         return {};
129     }
130 };
131 
132 /**
133  * Exposes the resources in a ResourceTable as symbols for SymbolTable.
134  * Instances of this class must outlive the encompassed ResourceTable.
135  * Lookups by ID are ignored.
136  */
137 class ResourceTableSymbolSource : public ISymbolSource {
138 public:
ResourceTableSymbolSource(ResourceTable * table)139     explicit ResourceTableSymbolSource(ResourceTable* table) : mTable(table) {
140     }
141 
142     std::unique_ptr<SymbolTable::Symbol> findByName(const ResourceName& name) override;
143 
findById(ResourceId id)144     std::unique_ptr<SymbolTable::Symbol> findById(ResourceId id) override {
145         return {};
146     }
147 
148 private:
149     ResourceTable* mTable;
150 
151     DISALLOW_COPY_AND_ASSIGN(ResourceTableSymbolSource);
152 };
153 
154 class AssetManagerSymbolSource : public ISymbolSource {
155 public:
156     AssetManagerSymbolSource() = default;
157 
158     bool addAssetPath(const StringPiece& path);
159 
160     std::unique_ptr<SymbolTable::Symbol> findByName(const ResourceName& name) override;
161     std::unique_ptr<SymbolTable::Symbol> findById(ResourceId id) override;
162     std::unique_ptr<SymbolTable::Symbol> findByReference(const Reference& ref) override;
163 
164 private:
165     android::AssetManager mAssets;
166 
167     DISALLOW_COPY_AND_ASSIGN(AssetManagerSymbolSource);
168 };
169 
170 } // namespace aapt
171 
172 #endif /* AAPT_PROCESS_SYMBOLTABLE_H */
173