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