• 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 "androidfw/StringPiece.h"
30 
31 #include <functional>
32 #include <map>
33 #include <memory>
34 #include <string>
35 #include <tuple>
36 #include <unordered_map>
37 #include <vector>
38 
39 namespace aapt {
40 
41 enum class SymbolState {
42   kUndefined,
43   kPrivate,
44   kPublic,
45 };
46 
47 /**
48  * The Public status of a resource.
49  */
50 struct Symbol {
51   SymbolState state = SymbolState::kUndefined;
52   Source source;
53 
54   // Whether this entry (originating from an overlay) can be added as a new resource.
55   bool allow_new = false;
56 
57   std::string comment;
58 };
59 
60 class ResourceConfigValue {
61  public:
62   /**
63    * The configuration for which this value is defined.
64    */
65   const ConfigDescription config;
66 
67   /**
68    * The product for which this value is defined.
69    */
70   const std::string product;
71 
72   /**
73    * The actual Value.
74    */
75   std::unique_ptr<Value> value;
76 
ResourceConfigValue(const ConfigDescription & config,const android::StringPiece & product)77   ResourceConfigValue(const ConfigDescription& config, const android::StringPiece& product)
78       : config(config), product(product.to_string()) {}
79 
80  private:
81   DISALLOW_COPY_AND_ASSIGN(ResourceConfigValue);
82 };
83 
84 /**
85  * Represents a resource entry, which may have
86  * varying values for each defined configuration.
87  */
88 class ResourceEntry {
89  public:
90   /**
91    * The name of the resource. Immutable, as
92    * this determines the order of this resource
93    * when doing lookups.
94    */
95   const std::string name;
96 
97   /**
98    * The entry ID for this resource.
99    */
100   Maybe<uint16_t> id;
101 
102   /**
103    * Whether this resource is public (and must maintain the same entry ID across
104    * builds).
105    */
106   Symbol symbol_status;
107 
108   /**
109    * The resource's values for each configuration.
110    */
111   std::vector<std::unique_ptr<ResourceConfigValue>> values;
112 
ResourceEntry(const android::StringPiece & name)113   explicit ResourceEntry(const android::StringPiece& name) : name(name.to_string()) {}
114 
115   ResourceConfigValue* FindValue(const ConfigDescription& config);
116   ResourceConfigValue* FindValue(const ConfigDescription& config,
117                                  const android::StringPiece& product);
118   ResourceConfigValue* FindOrCreateValue(const ConfigDescription& config,
119                                          const android::StringPiece& product);
120   std::vector<ResourceConfigValue*> FindAllValues(const ConfigDescription& config);
121   std::vector<ResourceConfigValue*> FindValuesIf(
122       const std::function<bool(ResourceConfigValue*)>& f);
123 
124  private:
125   DISALLOW_COPY_AND_ASSIGN(ResourceEntry);
126 };
127 
128 /**
129  * Represents a resource type, which holds entries defined
130  * for this type.
131  */
132 class ResourceTableType {
133  public:
134   /**
135    * The logical type of resource (string, drawable, layout, etc.).
136    */
137   const ResourceType type;
138 
139   /**
140    * The type ID for this resource.
141    */
142   Maybe<uint8_t> id;
143 
144   /**
145    * Whether this type is public (and must maintain the same
146    * type ID across builds).
147    */
148   Symbol symbol_status;
149 
150   /**
151    * List of resources for this type.
152    */
153   std::vector<std::unique_ptr<ResourceEntry>> entries;
154 
ResourceTableType(const ResourceType type)155   explicit ResourceTableType(const ResourceType type) : type(type) {}
156 
157   ResourceEntry* FindEntry(const android::StringPiece& name);
158   ResourceEntry* FindOrCreateEntry(const android::StringPiece& name);
159 
160  private:
161   DISALLOW_COPY_AND_ASSIGN(ResourceTableType);
162 };
163 
164 class ResourceTablePackage {
165  public:
166   Maybe<uint8_t> id;
167   std::string name;
168 
169   std::vector<std::unique_ptr<ResourceTableType>> types;
170 
171   ResourceTablePackage() = default;
172   ResourceTableType* FindType(ResourceType type);
173   ResourceTableType* FindOrCreateType(const ResourceType type);
174 
175  private:
176   DISALLOW_COPY_AND_ASSIGN(ResourceTablePackage);
177 };
178 
179 /**
180  * The container and index for all resources defined for an app. This gets
181  * flattened into a binary resource table (resources.arsc).
182  */
183 class ResourceTable {
184  public:
185   ResourceTable() = default;
186 
187   enum class CollisionResult { kKeepOriginal, kConflict, kTakeNew };
188 
189   using CollisionResolverFunc = std::function<CollisionResult(Value*, Value*)>;
190 
191   /**
192    * When a collision of resources occurs, this method decides which value to
193    * keep.
194    */
195   static CollisionResult ResolveValueCollision(Value* existing, Value* incoming);
196 
197   bool AddResource(const ResourceNameRef& name, const ConfigDescription& config,
198                    const android::StringPiece& product, std::unique_ptr<Value> value,
199                    IDiagnostics* diag);
200 
201   bool AddResource(const ResourceNameRef& name, const ResourceId& res_id,
202                    const ConfigDescription& config, const android::StringPiece& product,
203                    std::unique_ptr<Value> value, IDiagnostics* diag);
204 
205   bool AddFileReference(const ResourceNameRef& name, const ConfigDescription& config,
206                         const Source& source, const android::StringPiece& path, IDiagnostics* diag);
207 
208   bool AddFileReferenceAllowMangled(const ResourceNameRef& name, const ConfigDescription& config,
209                                     const Source& source, const android::StringPiece& path,
210                                     io::IFile* file, IDiagnostics* diag);
211 
212   /**
213    * Same as AddResource, but doesn't verify the validity of the name. This is
214    * used
215    * when loading resources from an existing binary resource table that may have
216    * mangled
217    * names.
218    */
219   bool AddResourceAllowMangled(const ResourceNameRef& name, const ConfigDescription& config,
220                                const android::StringPiece& product, std::unique_ptr<Value> value,
221                                IDiagnostics* diag);
222 
223   bool AddResourceAllowMangled(const ResourceNameRef& name, const ResourceId& id,
224                                const ConfigDescription& config, const android::StringPiece& product,
225                                std::unique_ptr<Value> value, IDiagnostics* diag);
226 
227   bool SetSymbolState(const ResourceNameRef& name, const ResourceId& res_id,
228                       const Symbol& symbol, IDiagnostics* diag);
229 
230   bool SetSymbolStateAllowMangled(const ResourceNameRef& name, const ResourceId& res_id,
231                                   const Symbol& symbol, IDiagnostics* diag);
232 
233   struct SearchResult {
234     ResourceTablePackage* package;
235     ResourceTableType* type;
236     ResourceEntry* entry;
237   };
238 
239   Maybe<SearchResult> FindResource(const ResourceNameRef& name);
240 
241   /**
242    * Returns the package struct with the given name, or nullptr if such a
243    * package does not
244    * exist. The empty string is a valid package and typically is used to
245    * represent the
246    * 'current' package before it is known to the ResourceTable.
247    */
248   ResourceTablePackage* FindPackage(const android::StringPiece& name);
249 
250   ResourceTablePackage* FindPackageById(uint8_t id);
251 
252   ResourceTablePackage* CreatePackage(const android::StringPiece& name, Maybe<uint8_t> id = {});
253 
254   /**
255    * The string pool used by this resource table. Values that reference strings
256    * must use
257    * this pool to create their strings.
258    *
259    * NOTE: `string_pool` must come before `packages` so that it is destroyed
260    * after.
261    * When `string_pool` references are destroyed (as they will be when
262    * `packages`
263    * is destroyed), they decrement a refCount, which would cause invalid
264    * memory access if the pool was already destroyed.
265    */
266   StringPool string_pool;
267 
268   /**
269    * The list of packages in this table, sorted alphabetically by package name.
270    */
271   std::vector<std::unique_ptr<ResourceTablePackage>> packages;
272 
273   // Set of dynamic packages that this table may reference. Their package names get encoded
274   // into the resources.arsc along with their compile-time assigned IDs.
275   std::map<size_t, std::string> included_packages_;
276 
277  private:
278   // The function type that validates a symbol name. Returns a non-empty StringPiece representing
279   // the offending character (which may be more than one byte in UTF-8). Returns an empty string
280   // if the name was valid.
281   using NameValidator = android::StringPiece(const android::StringPiece&);
282 
283   ResourceTablePackage* FindOrCreatePackage(const android::StringPiece& name);
284 
285   bool AddResourceImpl(const ResourceNameRef& name, const ResourceId& res_id,
286                        const ConfigDescription& config, const android::StringPiece& product,
287                        std::unique_ptr<Value> value, NameValidator name_validator,
288                        const CollisionResolverFunc& conflict_resolver, IDiagnostics* diag);
289 
290   bool AddFileReferenceImpl(const ResourceNameRef& name, const ConfigDescription& config,
291                             const Source& source, const android::StringPiece& path, io::IFile* file,
292                             NameValidator name_validator, IDiagnostics* diag);
293 
294   bool SetSymbolStateImpl(const ResourceNameRef& name, const ResourceId& res_id,
295                           const Symbol& symbol, NameValidator name_validator, IDiagnostics* diag);
296 
297   DISALLOW_COPY_AND_ASSIGN(ResourceTable);
298 };
299 
300 }  // namespace aapt
301 
302 #endif  // AAPT_RESOURCE_TABLE_H
303