• 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_RESOURCE_TABLE_H
18 #define AAPT_RESOURCE_TABLE_H
19 
20 #include "ConfigDescription.h"
21 #include "Diagnostics.h"
22 #include "Resource.h"
23 #include "ResourceValues.h"
24 #include "Source.h"
25 #include "StringPool.h"
26 #include "io/File.h"
27 
28 #include <android-base/macros.h>
29 #include <map>
30 #include <memory>
31 #include <string>
32 #include <tuple>
33 #include <unordered_map>
34 #include <vector>
35 
36 namespace aapt {
37 
38 enum class SymbolState {
39     kUndefined,
40     kPublic,
41     kPrivate
42 };
43 
44 /**
45  * The Public status of a resource.
46  */
47 struct Symbol {
48     SymbolState state = SymbolState::kUndefined;
49     Source source;
50     std::u16string comment;
51 };
52 
53 class ResourceConfigValue {
54 public:
55     /**
56      * The configuration for which this value is defined.
57      */
58     const ConfigDescription config;
59 
60     /**
61      * The product for which this value is defined.
62      */
63     const std::string product;
64 
65     /**
66      * The actual Value.
67      */
68     std::unique_ptr<Value> value;
69 
ResourceConfigValue(const ConfigDescription & config,const StringPiece & product)70     ResourceConfigValue(const ConfigDescription& config, const StringPiece& product) :
71             config(config), product(product.toString()) { }
72 
73 private:
74     DISALLOW_COPY_AND_ASSIGN(ResourceConfigValue);
75 };
76 
77 /**
78  * Represents a resource entry, which may have
79  * varying values for each defined configuration.
80  */
81 class ResourceEntry {
82 public:
83     /**
84      * The name of the resource. Immutable, as
85      * this determines the order of this resource
86      * when doing lookups.
87      */
88     const std::u16string name;
89 
90     /**
91      * The entry ID for this resource.
92      */
93     Maybe<uint16_t> id;
94 
95     /**
96      * Whether this resource is public (and must maintain the same entry ID across builds).
97      */
98     Symbol symbolStatus;
99 
100     /**
101      * The resource's values for each configuration.
102      */
103     std::vector<std::unique_ptr<ResourceConfigValue>> values;
104 
ResourceEntry(const StringPiece16 & name)105     ResourceEntry(const StringPiece16& name) : name(name.toString()) { }
106 
107     ResourceConfigValue* findValue(const ConfigDescription& config);
108     ResourceConfigValue* findValue(const ConfigDescription& config, const StringPiece& product);
109     ResourceConfigValue* findOrCreateValue(const ConfigDescription& config,
110                                            const StringPiece& product);
111     std::vector<ResourceConfigValue*> findAllValues(const ConfigDescription& config);
112 
113 private:
114     DISALLOW_COPY_AND_ASSIGN(ResourceEntry);
115 };
116 
117 /**
118  * Represents a resource type, which holds entries defined
119  * for this type.
120  */
121 class ResourceTableType {
122 public:
123     /**
124      * The logical type of resource (string, drawable, layout, etc.).
125      */
126     const ResourceType type;
127 
128     /**
129      * The type ID for this resource.
130      */
131     Maybe<uint8_t> id;
132 
133     /**
134      * Whether this type is public (and must maintain the same
135      * type ID across builds).
136      */
137     Symbol symbolStatus;
138 
139     /**
140      * List of resources for this type.
141      */
142     std::vector<std::unique_ptr<ResourceEntry>> entries;
143 
ResourceTableType(const ResourceType type)144     explicit ResourceTableType(const ResourceType type) : type(type) { }
145 
146     ResourceEntry* findEntry(const StringPiece16& name);
147     ResourceEntry* findOrCreateEntry(const StringPiece16& name);
148 
149 private:
150     DISALLOW_COPY_AND_ASSIGN(ResourceTableType);
151 };
152 
153 enum class PackageType {
154     System,
155     Vendor,
156     App,
157     Dynamic
158 };
159 
160 class ResourceTablePackage {
161 public:
162     PackageType type = PackageType::App;
163     Maybe<uint8_t> id;
164     std::u16string name;
165 
166     std::vector<std::unique_ptr<ResourceTableType>> types;
167 
168     ResourceTablePackage() = default;
169     ResourceTableType* findType(ResourceType type);
170     ResourceTableType* findOrCreateType(const ResourceType type);
171 
172 private:
173     DISALLOW_COPY_AND_ASSIGN(ResourceTablePackage);
174 };
175 
176 /**
177  * The container and index for all resources defined for an app. This gets
178  * flattened into a binary resource table (resources.arsc).
179  */
180 class ResourceTable {
181 public:
182     ResourceTable() = default;
183 
184     /**
185      * When a collision of resources occurs, this method decides which value to keep.
186      * Returns -1 if the existing value should be chosen.
187      * Returns 0 if the collision can not be resolved (error).
188      * Returns 1 if the incoming value should be chosen.
189      */
190     static int resolveValueCollision(Value* existing, Value* incoming);
191 
192     bool addResource(const ResourceNameRef& name,
193                      const ConfigDescription& config,
194                      const StringPiece& product,
195                      std::unique_ptr<Value> value,
196                      IDiagnostics* diag);
197 
198     bool addResource(const ResourceNameRef& name,
199                      const ResourceId resId,
200                      const ConfigDescription& config,
201                      const StringPiece& product,
202                      std::unique_ptr<Value> value,
203                      IDiagnostics* diag);
204 
205     bool addFileReference(const ResourceNameRef& name,
206                               const ConfigDescription& config,
207                               const Source& source,
208                               const StringPiece16& path,
209                               IDiagnostics* diag);
210 
211     bool addFileReferenceAllowMangled(const ResourceNameRef& name,
212                                       const ConfigDescription& config,
213                                       const Source& source,
214                                       const StringPiece16& path,
215                                       io::IFile* file,
216                                       IDiagnostics* diag);
217 
218     /**
219      * Same as addResource, but doesn't verify the validity of the name. This is used
220      * when loading resources from an existing binary resource table that may have mangled
221      * names.
222      */
223     bool addResourceAllowMangled(const ResourceNameRef& name,
224                                  const ConfigDescription& config,
225                                  const StringPiece& product,
226                                  std::unique_ptr<Value> value,
227                                  IDiagnostics* diag);
228 
229     bool addResourceAllowMangled(const ResourceNameRef& name,
230                                  const ResourceId id,
231                                  const ConfigDescription& config,
232                                  const StringPiece& product,
233                                  std::unique_ptr<Value> value,
234                                  IDiagnostics* diag);
235 
236     bool setSymbolState(const ResourceNameRef& name,
237                         const ResourceId resId,
238                         const Symbol& symbol,
239                         IDiagnostics* diag);
240 
241     bool setSymbolStateAllowMangled(const ResourceNameRef& name,
242                                     const ResourceId resId,
243                                     const Symbol& symbol,
244                                     IDiagnostics* diag);
245 
246     struct SearchResult {
247         ResourceTablePackage* package;
248         ResourceTableType* type;
249         ResourceEntry* entry;
250     };
251 
252     Maybe<SearchResult> findResource(const ResourceNameRef& name);
253 
254     /**
255      * The string pool used by this resource table. Values that reference strings must use
256      * this pool to create their strings.
257      *
258      * NOTE: `stringPool` must come before `packages` so that it is destroyed after.
259      * When `string pool` references are destroyed (as they will be when `packages`
260      * is destroyed), they decrement a refCount, which would cause invalid
261      * memory access if the pool was already destroyed.
262      */
263     StringPool stringPool;
264 
265     /**
266      * The list of packages in this table, sorted alphabetically by package name.
267      */
268     std::vector<std::unique_ptr<ResourceTablePackage>> packages;
269 
270     /**
271      * Returns the package struct with the given name, or nullptr if such a package does not
272      * exist. The empty string is a valid package and typically is used to represent the
273      * 'current' package before it is known to the ResourceTable.
274      */
275     ResourceTablePackage* findPackage(const StringPiece16& name);
276 
277     ResourceTablePackage* findPackageById(uint8_t id);
278 
279     ResourceTablePackage* createPackage(const StringPiece16& name, Maybe<uint8_t> id = {});
280 
281 private:
282     ResourceTablePackage* findOrCreatePackage(const StringPiece16& name);
283 
284     bool addFileReferenceImpl(const ResourceNameRef& name,
285                               const ConfigDescription& config,
286                               const Source& source,
287                               const StringPiece16& path,
288                               io::IFile* file,
289                               const char16_t* validChars,
290                               IDiagnostics* diag);
291 
292     bool addResourceImpl(const ResourceNameRef& name,
293                          ResourceId resId,
294                          const ConfigDescription& config,
295                          const StringPiece& product,
296                          std::unique_ptr<Value> value,
297                          const char16_t* validChars,
298                          std::function<int(Value*,Value*)> conflictResolver,
299                          IDiagnostics* diag);
300 
301     bool setSymbolStateImpl(const ResourceNameRef& name,
302                             ResourceId resId,
303                             const Symbol& symbol,
304                             const char16_t* validChars,
305                             IDiagnostics* diag);
306 
307     DISALLOW_COPY_AND_ASSIGN(ResourceTable);
308 };
309 
310 } // namespace aapt
311 
312 #endif // AAPT_RESOURCE_TABLE_H
313