• 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_H
18 #define AAPT_RESOURCE_H
19 
20 #include <iomanip>
21 #include <limits>
22 #include <sstream>
23 #include <string>
24 #include <tuple>
25 #include <vector>
26 
27 #include "androidfw/ConfigDescription.h"
28 #include "androidfw/StringPiece.h"
29 #include "utils/JenkinsHash.h"
30 
31 #include "Source.h"
32 
33 namespace aapt {
34 
35 /**
36  * The various types of resource types available. Corresponds
37  * to the 'type' in package:type/entry.
38  */
39 enum class ResourceType {
40   kAnim,
41   kAnimator,
42   kArray,
43   kAttr,
44   kAttrPrivate,
45   kBool,
46   kColor,
47 
48   // Not really a type, but it shows up in some CTS tests and
49   // we need to continue respecting it.
50   kConfigVarying,
51 
52   kDimen,
53   kDrawable,
54   kFont,
55   kFraction,
56   kId,
57   kInteger,
58   kInterpolator,
59   kLayout,
60   kMacro,
61   kMenu,
62   kMipmap,
63   kNavigation,
64   kPlurals,
65   kRaw,
66   kString,
67   kStyle,
68   kStyleable,
69   kTransition,
70   kXml,
71 };
72 
73 android::StringPiece to_string(ResourceType type);
74 
75 /**
76  * Returns a pointer to a valid ResourceType, or nullptr if the string was invalid.
77  */
78 const ResourceType* ParseResourceType(const android::StringPiece& str);
79 
80 /**
81  * A resource's name. This can uniquely identify
82  * a resource in the ResourceTable.
83  */
84 struct ResourceName {
85   std::string package;
86   ResourceType type = ResourceType::kRaw;
87   std::string entry;
88 
89   ResourceName() = default;
90   ResourceName(const android::StringPiece& p, ResourceType t, const android::StringPiece& e);
91 
92   int compare(const ResourceName& other) const;
93 
94   bool is_valid() const;
95   std::string to_string() const;
96 };
97 
98 /**
99  * Same as ResourceName, but uses StringPieces instead.
100  * Use this if you need to avoid copying and know that
101  * the lifetime of this object is shorter than that
102  * of the original string.
103  */
104 struct ResourceNameRef {
105   android::StringPiece package;
106   ResourceType type = ResourceType::kRaw;
107   android::StringPiece entry;
108 
109   ResourceNameRef() = default;
110   ResourceNameRef(const ResourceNameRef&) = default;
111   ResourceNameRef(ResourceNameRef&&) = default;
112   ResourceNameRef(const ResourceName& rhs);  // NOLINT(google-explicit-constructor)
113   ResourceNameRef(const android::StringPiece& p, ResourceType t, const android::StringPiece& e);
114   ResourceNameRef& operator=(const ResourceNameRef& rhs) = default;
115   ResourceNameRef& operator=(ResourceNameRef&& rhs) = default;
116   ResourceNameRef& operator=(const ResourceName& rhs);
117 
118   bool is_valid() const;
119 
120   ResourceName ToResourceName() const;
121   std::string to_string() const;
122 };
123 
124 constexpr const uint8_t kAppPackageId = 0x7fu;
125 constexpr const uint8_t kFrameworkPackageId = 0x01u;
126 
127 /**
128  * A binary identifier representing a resource. Internally it
129  * is a 32bit integer split as follows:
130  *
131  * 0xPPTTEEEE
132  *
133  * PP: 8 bit package identifier. 0x01 is reserved for system
134  *     and 0x7f is reserved for the running app.
135  * TT: 8 bit type identifier. 0x00 is invalid.
136  * EEEE: 16 bit entry identifier.
137  */
138 struct ResourceId {
139   uint32_t id;
140 
141   ResourceId();
142   ResourceId(const ResourceId& rhs) = default;
143   ResourceId(uint32_t res_id);  // NOLINT(google-explicit-constructor)
144   ResourceId(uint8_t p, uint8_t t, uint16_t e);
145 
146   // Returns true if the ID is a valid ID that is not dynamic (package ID cannot be 0)
147   bool is_valid_static() const;
148 
149   // Returns true if the ID is a valid ID or dynamic ID (package ID can be 0).
150   bool is_valid() const;
151 
152   uint8_t package_id() const;
153   uint8_t type_id() const;
154   uint16_t entry_id() const;
155 
156   std::string to_string() const;
157 };
158 
159 struct SourcedResourceName {
160   ResourceName name;
161   size_t line;
162 };
163 
164 struct ResourceFile {
165   enum class Type {
166     kUnknown,
167     kPng,
168     kBinaryXml,
169     kProtoXml,
170   };
171 
172   // Name
173   ResourceName name;
174 
175   // Configuration
176   android::ConfigDescription config;
177 
178   // Type
179   Type type;
180 
181   // Source
182   Source source;
183 
184   // Exported symbols
185   std::vector<SourcedResourceName> exported_symbols;
186 };
187 
188 /**
189  * Useful struct used as a key to represent a unique resource in associative
190  * containers.
191  */
192 struct ResourceKey {
193   ResourceName name;
194   android::ConfigDescription config;
195 };
196 
197 bool operator<(const ResourceKey& a, const ResourceKey& b);
198 
199 /**
200  * Useful struct used as a key to represent a unique resource in associative
201  * containers.
202  * Holds a reference to the name, so that name better live longer than this key!
203  */
204 struct ResourceKeyRef {
205   ResourceNameRef name;
206   android::ConfigDescription config;
207 
208   ResourceKeyRef() = default;
ResourceKeyRefResourceKeyRef209   ResourceKeyRef(const ResourceNameRef& n, const android::ConfigDescription& c)
210       : name(n), config(c) {}
211 
212   /**
213    * Prevent taking a reference to a temporary. This is bad.
214    */
215   ResourceKeyRef(ResourceName&& n, const android::ConfigDescription& c) = delete;
216 };
217 
218 bool operator<(const ResourceKeyRef& a, const ResourceKeyRef& b);
219 
220 //
221 // ResourceId implementation.
222 //
223 
ResourceId()224 inline ResourceId::ResourceId() : id(0) {}
225 
ResourceId(uint32_t res_id)226 inline ResourceId::ResourceId(uint32_t res_id) : id(res_id) {}
227 
ResourceId(uint8_t p,uint8_t t,uint16_t e)228 inline ResourceId::ResourceId(uint8_t p, uint8_t t, uint16_t e)
229     : id((p << 24) | (t << 16) | e) {}
230 
is_valid_static()231 inline bool ResourceId::is_valid_static() const {
232   return (id & 0xff000000u) != 0 && (id & 0x00ff0000u) != 0;
233 }
234 
is_valid()235 inline bool ResourceId::is_valid() const {
236   return (id & 0x00ff0000u) != 0;
237 }
238 
package_id()239 inline uint8_t ResourceId::package_id() const {
240   return static_cast<uint8_t>(id >> 24);
241 }
242 
type_id()243 inline uint8_t ResourceId::type_id() const {
244   return static_cast<uint8_t>(id >> 16);
245 }
246 
entry_id()247 inline uint16_t ResourceId::entry_id() const {
248   return static_cast<uint16_t>(id);
249 }
250 
251 inline bool operator<(const ResourceId& lhs, const ResourceId& rhs) {
252   return lhs.id < rhs.id;
253 }
254 
255 inline bool operator>(const ResourceId& lhs, const ResourceId& rhs) {
256   return lhs.id > rhs.id;
257 }
258 
259 inline bool operator==(const ResourceId& lhs, const ResourceId& rhs) {
260   return lhs.id == rhs.id;
261 }
262 
263 inline bool operator!=(const ResourceId& lhs, const ResourceId& rhs) {
264   return lhs.id != rhs.id;
265 }
266 
267 inline ::std::ostream& operator<<(::std::ostream& out, const ResourceId& res_id) {
268   return out << res_id.to_string();
269 }
270 
271 // For generic code to call 'using std::to_string; to_string(T);'.
to_string(const ResourceId & id)272 inline std::string to_string(const ResourceId& id) {
273   return id.to_string();
274 }
275 
276 // Helper to compare resource IDs, moving dynamic IDs after framework IDs.
cmp_ids_dynamic_after_framework(const ResourceId & a,const ResourceId & b)277 inline bool cmp_ids_dynamic_after_framework(const ResourceId& a, const ResourceId& b) {
278   // If one of a and b is from the framework package (package ID 0x01), and the
279   // other is a dynamic ID (package ID 0x00), then put the dynamic ID after the
280   // framework ID. This ensures that when AssetManager resolves the dynamic IDs,
281   // they will be in sorted order as expected by AssetManager.
282   if ((a.package_id() == kFrameworkPackageId && b.package_id() == 0x00) ||
283       (a.package_id() == 0x00 && b.package_id() == kFrameworkPackageId)) {
284     return b < a;
285   }
286   return a < b;
287 }
288 
289 //
290 // ResourceType implementation.
291 //
292 
293 inline ::std::ostream& operator<<(::std::ostream& out, const ResourceType& val) {
294   return out << to_string(val);
295 }
296 
297 //
298 // ResourceName implementation.
299 //
300 
ResourceName(const android::StringPiece & p,ResourceType t,const android::StringPiece & e)301 inline ResourceName::ResourceName(const android::StringPiece& p, ResourceType t,
302                                   const android::StringPiece& e)
303     : package(p.to_string()), type(t), entry(e.to_string()) {}
304 
compare(const ResourceName & other)305 inline int ResourceName::compare(const ResourceName& other) const {
306   int cmp = package.compare(other.package);
307   if (cmp != 0) return cmp;
308   cmp = static_cast<int>(type) - static_cast<int>(other.type);
309   if (cmp != 0) return cmp;
310   cmp = entry.compare(other.entry);
311   return cmp;
312 }
313 
is_valid()314 inline bool ResourceName::is_valid() const {
315   return !package.empty() && !entry.empty();
316 }
317 
318 inline bool operator<(const ResourceName& lhs, const ResourceName& rhs) {
319   return std::tie(lhs.package, lhs.type, lhs.entry) <
320          std::tie(rhs.package, rhs.type, rhs.entry);
321 }
322 
323 inline bool operator==(const ResourceName& lhs, const ResourceName& rhs) {
324   return std::tie(lhs.package, lhs.type, lhs.entry) ==
325          std::tie(rhs.package, rhs.type, rhs.entry);
326 }
327 
328 inline bool operator!=(const ResourceName& lhs, const ResourceName& rhs) {
329   return std::tie(lhs.package, lhs.type, lhs.entry) !=
330          std::tie(rhs.package, rhs.type, rhs.entry);
331 }
332 
333 inline ::std::ostream& operator<<(::std::ostream& out, const ResourceName& name) {
334   return out << name.to_string();
335 }
336 
337 //
338 // ResourceNameRef implementation.
339 //
340 
ResourceNameRef(const ResourceName & rhs)341 inline ResourceNameRef::ResourceNameRef(const ResourceName& rhs)
342     : package(rhs.package), type(rhs.type), entry(rhs.entry) {}
343 
ResourceNameRef(const android::StringPiece & p,ResourceType t,const android::StringPiece & e)344 inline ResourceNameRef::ResourceNameRef(const android::StringPiece& p, ResourceType t,
345                                         const android::StringPiece& e)
346     : package(p), type(t), entry(e) {}
347 
348 inline ResourceNameRef& ResourceNameRef::operator=(const ResourceName& rhs) {
349   package = rhs.package;
350   type = rhs.type;
351   entry = rhs.entry;
352   return *this;
353 }
354 
ToResourceName()355 inline ResourceName ResourceNameRef::ToResourceName() const {
356   return ResourceName(package, type, entry);
357 }
358 
is_valid()359 inline bool ResourceNameRef::is_valid() const {
360   return !package.empty() && !entry.empty();
361 }
362 
363 inline bool operator<(const ResourceNameRef& lhs, const ResourceNameRef& rhs) {
364   return std::tie(lhs.package, lhs.type, lhs.entry) <
365          std::tie(rhs.package, rhs.type, rhs.entry);
366 }
367 
368 inline bool operator==(const ResourceNameRef& lhs, const ResourceNameRef& rhs) {
369   return std::tie(lhs.package, lhs.type, lhs.entry) ==
370          std::tie(rhs.package, rhs.type, rhs.entry);
371 }
372 
373 inline bool operator!=(const ResourceNameRef& lhs, const ResourceNameRef& rhs) {
374   return std::tie(lhs.package, lhs.type, lhs.entry) !=
375          std::tie(rhs.package, rhs.type, rhs.entry);
376 }
377 
378 inline ::std::ostream& operator<<(::std::ostream& out, const ResourceNameRef& name) {
379   return out << name.to_string();
380 }
381 
382 inline bool operator<(const ResourceName& lhs, const ResourceNameRef& b) {
383   return ResourceNameRef(lhs) < b;
384 }
385 
386 inline bool operator!=(const ResourceName& lhs, const ResourceNameRef& rhs) {
387   return ResourceNameRef(lhs) != rhs;
388 }
389 
390 inline bool operator==(const SourcedResourceName& lhs, const SourcedResourceName& rhs) {
391   return lhs.name == rhs.name && lhs.line == rhs.line;
392 }
393 
394 }  // namespace aapt
395 
396 namespace std {
397 
398 template <>
399 struct hash<aapt::ResourceName> {
400   size_t operator()(const aapt::ResourceName& name) const {
401     android::hash_t h = 0;
402     h = android::JenkinsHashMix(h, static_cast<uint32_t>(hash<string>()(name.package)));
403     h = android::JenkinsHashMix(h, static_cast<uint32_t>(name.type));
404     h = android::JenkinsHashMix(h, static_cast<uint32_t>(hash<string>()(name.entry)));
405     return static_cast<size_t>(h);
406   }
407 };
408 
409 template <>
410 struct hash<aapt::ResourceId> {
411   size_t operator()(const aapt::ResourceId& id) const {
412     return id.id;
413   }
414 };
415 
416 }  // namespace std
417 
418 #endif  // AAPT_RESOURCE_H
419