]> git.saurik.com Git - android/aapt.git/blob - AaptAssets.h
Use "ldrtl" and "ldltr" config qualifiers for RTL / LTR resources
[android/aapt.git] / AaptAssets.h
1 //
2 // Copyright 2006 The Android Open Source Project
3 //
4 // Information about assets being operated on.
5 //
6 #ifndef __AAPT_ASSETS_H
7 #define __AAPT_ASSETS_H
8
9 #include <stdlib.h>
10 #include <androidfw/AssetManager.h>
11 #include <androidfw/ResourceTypes.h>
12 #include <utils/KeyedVector.h>
13 #include <utils/RefBase.h>
14 #include <utils/SortedVector.h>
15 #include <utils/String8.h>
16 #include <utils/String8.h>
17 #include <utils/Vector.h>
18 #include "ZipFile.h"
19
20 #include "Bundle.h"
21 #include "SourcePos.h"
22
23 using namespace android;
24
25
26 extern const char * const gDefaultIgnoreAssets;
27 extern const char * gUserIgnoreAssets;
28
29 bool valid_symbol_name(const String8& str);
30
31 class AaptAssets;
32
33 enum {
34 AXIS_NONE = 0,
35 AXIS_MCC = 1,
36 AXIS_MNC,
37 AXIS_LANGUAGE,
38 AXIS_REGION,
39 AXIS_SCREENLAYOUTSIZE,
40 AXIS_SCREENLAYOUTLONG,
41 AXIS_ORIENTATION,
42 AXIS_UIMODETYPE,
43 AXIS_UIMODENIGHT,
44 AXIS_DENSITY,
45 AXIS_TOUCHSCREEN,
46 AXIS_KEYSHIDDEN,
47 AXIS_KEYBOARD,
48 AXIS_NAVHIDDEN,
49 AXIS_NAVIGATION,
50 AXIS_SCREENSIZE,
51 AXIS_SMALLESTSCREENWIDTHDP,
52 AXIS_SCREENWIDTHDP,
53 AXIS_SCREENHEIGHTDP,
54 AXIS_LAYOUTDIR,
55 AXIS_VERSION,
56
57 AXIS_START = AXIS_MCC,
58 AXIS_END = AXIS_VERSION,
59 };
60
61 /**
62 * This structure contains a specific variation of a single file out
63 * of all the variations it can have that we can have.
64 */
65 struct AaptGroupEntry
66 {
67 public:
68 AaptGroupEntry() : mParamsChanged(true) { }
69 AaptGroupEntry(const String8& _locale, const String8& _vendor)
70 : locale(_locale), vendor(_vendor), mParamsChanged(true) { }
71
72 bool initFromDirName(const char* dir, String8* resType);
73
74 static status_t parseNamePart(const String8& part, int* axis, uint32_t* value);
75
76 static uint32_t getConfigValueForAxis(const ResTable_config& config, int axis);
77
78 static bool configSameExcept(const ResTable_config& config,
79 const ResTable_config& otherConfig, int axis);
80
81 static bool getMccName(const char* name, ResTable_config* out = NULL);
82 static bool getMncName(const char* name, ResTable_config* out = NULL);
83 static bool getLocaleName(const char* name, ResTable_config* out = NULL);
84 static bool getScreenLayoutSizeName(const char* name, ResTable_config* out = NULL);
85 static bool getScreenLayoutLongName(const char* name, ResTable_config* out = NULL);
86 static bool getOrientationName(const char* name, ResTable_config* out = NULL);
87 static bool getUiModeTypeName(const char* name, ResTable_config* out = NULL);
88 static bool getUiModeNightName(const char* name, ResTable_config* out = NULL);
89 static bool getDensityName(const char* name, ResTable_config* out = NULL);
90 static bool getTouchscreenName(const char* name, ResTable_config* out = NULL);
91 static bool getKeysHiddenName(const char* name, ResTable_config* out = NULL);
92 static bool getKeyboardName(const char* name, ResTable_config* out = NULL);
93 static bool getNavigationName(const char* name, ResTable_config* out = NULL);
94 static bool getNavHiddenName(const char* name, ResTable_config* out = NULL);
95 static bool getScreenSizeName(const char* name, ResTable_config* out = NULL);
96 static bool getSmallestScreenWidthDpName(const char* name, ResTable_config* out = NULL);
97 static bool getScreenWidthDpName(const char* name, ResTable_config* out = NULL);
98 static bool getScreenHeightDpName(const char* name, ResTable_config* out = NULL);
99 static bool getLayoutDirectionName(const char* name, ResTable_config* out = NULL);
100 static bool getVersionName(const char* name, ResTable_config* out = NULL);
101
102 int compare(const AaptGroupEntry& o) const;
103
104 const ResTable_config& toParams() const;
105
106 inline bool operator<(const AaptGroupEntry& o) const { return compare(o) < 0; }
107 inline bool operator<=(const AaptGroupEntry& o) const { return compare(o) <= 0; }
108 inline bool operator==(const AaptGroupEntry& o) const { return compare(o) == 0; }
109 inline bool operator!=(const AaptGroupEntry& o) const { return compare(o) != 0; }
110 inline bool operator>=(const AaptGroupEntry& o) const { return compare(o) >= 0; }
111 inline bool operator>(const AaptGroupEntry& o) const { return compare(o) > 0; }
112
113 String8 toString() const;
114 String8 toDirName(const String8& resType) const;
115
116 const String8& getVersionString() const { return version; }
117
118 private:
119 String8 mcc;
120 String8 mnc;
121 String8 locale;
122 String8 vendor;
123 String8 smallestScreenWidthDp;
124 String8 screenWidthDp;
125 String8 screenHeightDp;
126 String8 screenLayoutSize;
127 String8 screenLayoutLong;
128 String8 orientation;
129 String8 uiModeType;
130 String8 uiModeNight;
131 String8 density;
132 String8 touchscreen;
133 String8 keysHidden;
134 String8 keyboard;
135 String8 navHidden;
136 String8 navigation;
137 String8 screenSize;
138 String8 layoutDirection;
139 String8 version;
140
141 mutable bool mParamsChanged;
142 mutable ResTable_config mParams;
143 };
144
145 inline int compare_type(const AaptGroupEntry& lhs, const AaptGroupEntry& rhs)
146 {
147 return lhs.compare(rhs);
148 }
149
150 inline int strictly_order_type(const AaptGroupEntry& lhs, const AaptGroupEntry& rhs)
151 {
152 return compare_type(lhs, rhs) < 0;
153 }
154
155 class AaptGroup;
156 class FilePathStore;
157
158 /**
159 * A single asset file we know about.
160 */
161 class AaptFile : public RefBase
162 {
163 public:
164 AaptFile(const String8& sourceFile, const AaptGroupEntry& groupEntry,
165 const String8& resType)
166 : mGroupEntry(groupEntry)
167 , mResourceType(resType)
168 , mSourceFile(sourceFile)
169 , mData(NULL)
170 , mDataSize(0)
171 , mBufferSize(0)
172 , mCompression(ZipEntry::kCompressStored)
173 {
174 //printf("new AaptFile created %s\n", (const char*)sourceFile);
175 }
176 virtual ~AaptFile() {
177 free(mData);
178 }
179
180 const String8& getPath() const { return mPath; }
181 const AaptGroupEntry& getGroupEntry() const { return mGroupEntry; }
182
183 // Data API. If there is data attached to the file,
184 // getSourceFile() is not used.
185 bool hasData() const { return mData != NULL; }
186 const void* getData() const { return mData; }
187 size_t getSize() const { return mDataSize; }
188 void* editData(size_t size);
189 void* editData(size_t* outSize = NULL);
190 void* padData(size_t wordSize);
191 status_t writeData(const void* data, size_t size);
192 void clearData();
193
194 const String8& getResourceType() const { return mResourceType; }
195
196 // File API. If the file does not hold raw data, this is
197 // a full path to a file on the filesystem that holds its data.
198 const String8& getSourceFile() const { return mSourceFile; }
199
200 String8 getPrintableSource() const;
201
202 // Desired compression method, as per utils/ZipEntry.h. For example,
203 // no compression is ZipEntry::kCompressStored.
204 int getCompressionMethod() const { return mCompression; }
205 void setCompressionMethod(int c) { mCompression = c; }
206 private:
207 friend class AaptGroup;
208
209 String8 mPath;
210 AaptGroupEntry mGroupEntry;
211 String8 mResourceType;
212 String8 mSourceFile;
213 void* mData;
214 size_t mDataSize;
215 size_t mBufferSize;
216 int mCompression;
217 };
218
219 /**
220 * A group of related files (the same file, with different
221 * vendor/locale variations).
222 */
223 class AaptGroup : public RefBase
224 {
225 public:
226 AaptGroup(const String8& leaf, const String8& path)
227 : mLeaf(leaf), mPath(path) { }
228 virtual ~AaptGroup() { }
229
230 const String8& getLeaf() const { return mLeaf; }
231
232 // Returns the relative path after the AaptGroupEntry dirs.
233 const String8& getPath() const { return mPath; }
234
235 const DefaultKeyedVector<AaptGroupEntry, sp<AaptFile> >& getFiles() const
236 { return mFiles; }
237
238 status_t addFile(const sp<AaptFile>& file);
239 void removeFile(size_t index);
240
241 void print(const String8& prefix) const;
242
243 String8 getPrintableSource() const;
244
245 private:
246 String8 mLeaf;
247 String8 mPath;
248
249 DefaultKeyedVector<AaptGroupEntry, sp<AaptFile> > mFiles;
250 };
251
252 /**
253 * A single directory of assets, which can contain files and other
254 * sub-directories.
255 */
256 class AaptDir : public RefBase
257 {
258 public:
259 AaptDir(const String8& leaf, const String8& path)
260 : mLeaf(leaf), mPath(path) { }
261 virtual ~AaptDir() { }
262
263 const String8& getLeaf() const { return mLeaf; }
264
265 const String8& getPath() const { return mPath; }
266
267 const DefaultKeyedVector<String8, sp<AaptGroup> >& getFiles() const { return mFiles; }
268 const DefaultKeyedVector<String8, sp<AaptDir> >& getDirs() const { return mDirs; }
269
270 virtual status_t addFile(const String8& name, const sp<AaptGroup>& file);
271
272 void removeFile(const String8& name);
273 void removeDir(const String8& name);
274
275 /*
276 * Perform some sanity checks on the names of files and directories here.
277 * In particular:
278 * - Check for illegal chars in filenames.
279 * - Check filename length.
280 * - Check for presence of ".gz" and non-".gz" copies of same file.
281 * - Check for multiple files whose names match in a case-insensitive
282 * fashion (problematic for some systems).
283 *
284 * Comparing names against all other names is O(n^2). We could speed
285 * it up some by sorting the entries and being smarter about what we
286 * compare against, but I'm not expecting to have enough files in a
287 * single directory to make a noticeable difference in speed.
288 *
289 * Note that sorting here is not enough to guarantee that the package
290 * contents are sorted -- subsequent updates can rearrange things.
291 */
292 status_t validate() const;
293
294 void print(const String8& prefix) const;
295
296 String8 getPrintableSource() const;
297
298 private:
299 friend class AaptAssets;
300
301 status_t addDir(const String8& name, const sp<AaptDir>& dir);
302 sp<AaptDir> makeDir(const String8& name);
303 status_t addLeafFile(const String8& leafName,
304 const sp<AaptFile>& file);
305 virtual ssize_t slurpFullTree(Bundle* bundle,
306 const String8& srcDir,
307 const AaptGroupEntry& kind,
308 const String8& resType,
309 sp<FilePathStore>& fullResPaths);
310
311 String8 mLeaf;
312 String8 mPath;
313
314 DefaultKeyedVector<String8, sp<AaptGroup> > mFiles;
315 DefaultKeyedVector<String8, sp<AaptDir> > mDirs;
316 };
317
318 /**
319 * All information we know about a particular symbol.
320 */
321 class AaptSymbolEntry
322 {
323 public:
324 AaptSymbolEntry()
325 : isPublic(false), isJavaSymbol(false), typeCode(TYPE_UNKNOWN)
326 {
327 }
328 AaptSymbolEntry(const String8& _name)
329 : name(_name), isPublic(false), isJavaSymbol(false), typeCode(TYPE_UNKNOWN)
330 {
331 }
332 AaptSymbolEntry(const AaptSymbolEntry& o)
333 : name(o.name), sourcePos(o.sourcePos), isPublic(o.isPublic)
334 , isJavaSymbol(o.isJavaSymbol), comment(o.comment), typeComment(o.typeComment)
335 , typeCode(o.typeCode), int32Val(o.int32Val), stringVal(o.stringVal)
336 {
337 }
338 AaptSymbolEntry operator=(const AaptSymbolEntry& o)
339 {
340 sourcePos = o.sourcePos;
341 isPublic = o.isPublic;
342 isJavaSymbol = o.isJavaSymbol;
343 comment = o.comment;
344 typeComment = o.typeComment;
345 typeCode = o.typeCode;
346 int32Val = o.int32Val;
347 stringVal = o.stringVal;
348 return *this;
349 }
350
351 const String8 name;
352
353 SourcePos sourcePos;
354 bool isPublic;
355 bool isJavaSymbol;
356
357 String16 comment;
358 String16 typeComment;
359
360 enum {
361 TYPE_UNKNOWN = 0,
362 TYPE_INT32,
363 TYPE_STRING
364 };
365
366 int typeCode;
367
368 // Value. May be one of these.
369 int32_t int32Val;
370 String8 stringVal;
371 };
372
373 /**
374 * A group of related symbols (such as indices into a string block)
375 * that have been generated from the assets.
376 */
377 class AaptSymbols : public RefBase
378 {
379 public:
380 AaptSymbols() { }
381 virtual ~AaptSymbols() { }
382
383 status_t addSymbol(const String8& name, int32_t value, const SourcePos& pos) {
384 if (!check_valid_symbol_name(name, pos, "symbol")) {
385 return BAD_VALUE;
386 }
387 AaptSymbolEntry& sym = edit_symbol(name, &pos);
388 sym.typeCode = AaptSymbolEntry::TYPE_INT32;
389 sym.int32Val = value;
390 return NO_ERROR;
391 }
392
393 status_t addStringSymbol(const String8& name, const String8& value,
394 const SourcePos& pos) {
395 if (!check_valid_symbol_name(name, pos, "symbol")) {
396 return BAD_VALUE;
397 }
398 AaptSymbolEntry& sym = edit_symbol(name, &pos);
399 sym.typeCode = AaptSymbolEntry::TYPE_STRING;
400 sym.stringVal = value;
401 return NO_ERROR;
402 }
403
404 status_t makeSymbolPublic(const String8& name, const SourcePos& pos) {
405 if (!check_valid_symbol_name(name, pos, "symbol")) {
406 return BAD_VALUE;
407 }
408 AaptSymbolEntry& sym = edit_symbol(name, &pos);
409 sym.isPublic = true;
410 return NO_ERROR;
411 }
412
413 status_t makeSymbolJavaSymbol(const String8& name, const SourcePos& pos) {
414 if (!check_valid_symbol_name(name, pos, "symbol")) {
415 return BAD_VALUE;
416 }
417 AaptSymbolEntry& sym = edit_symbol(name, &pos);
418 sym.isJavaSymbol = true;
419 return NO_ERROR;
420 }
421
422 void appendComment(const String8& name, const String16& comment, const SourcePos& pos) {
423 if (comment.size() <= 0) {
424 return;
425 }
426 AaptSymbolEntry& sym = edit_symbol(name, &pos);
427 if (sym.comment.size() == 0) {
428 sym.comment = comment;
429 } else {
430 sym.comment.append(String16("\n"));
431 sym.comment.append(comment);
432 }
433 }
434
435 void appendTypeComment(const String8& name, const String16& comment) {
436 if (comment.size() <= 0) {
437 return;
438 }
439 AaptSymbolEntry& sym = edit_symbol(name, NULL);
440 if (sym.typeComment.size() == 0) {
441 sym.typeComment = comment;
442 } else {
443 sym.typeComment.append(String16("\n"));
444 sym.typeComment.append(comment);
445 }
446 }
447
448 sp<AaptSymbols> addNestedSymbol(const String8& name, const SourcePos& pos) {
449 if (!check_valid_symbol_name(name, pos, "nested symbol")) {
450 return NULL;
451 }
452
453 sp<AaptSymbols> sym = mNestedSymbols.valueFor(name);
454 if (sym == NULL) {
455 sym = new AaptSymbols();
456 mNestedSymbols.add(name, sym);
457 }
458
459 return sym;
460 }
461
462 status_t applyJavaSymbols(const sp<AaptSymbols>& javaSymbols);
463
464 const KeyedVector<String8, AaptSymbolEntry>& getSymbols() const
465 { return mSymbols; }
466 const DefaultKeyedVector<String8, sp<AaptSymbols> >& getNestedSymbols() const
467 { return mNestedSymbols; }
468
469 const String16& getComment(const String8& name) const
470 { return get_symbol(name).comment; }
471 const String16& getTypeComment(const String8& name) const
472 { return get_symbol(name).typeComment; }
473
474 private:
475 bool check_valid_symbol_name(const String8& symbol, const SourcePos& pos, const char* label) {
476 if (valid_symbol_name(symbol)) {
477 return true;
478 }
479 pos.error("invalid %s: '%s'\n", label, symbol.string());
480 return false;
481 }
482 AaptSymbolEntry& edit_symbol(const String8& symbol, const SourcePos* pos) {
483 ssize_t i = mSymbols.indexOfKey(symbol);
484 if (i < 0) {
485 i = mSymbols.add(symbol, AaptSymbolEntry(symbol));
486 }
487 AaptSymbolEntry& sym = mSymbols.editValueAt(i);
488 if (pos != NULL && sym.sourcePos.line < 0) {
489 sym.sourcePos = *pos;
490 }
491 return sym;
492 }
493 const AaptSymbolEntry& get_symbol(const String8& symbol) const {
494 ssize_t i = mSymbols.indexOfKey(symbol);
495 if (i >= 0) {
496 return mSymbols.valueAt(i);
497 }
498 return mDefSymbol;
499 }
500
501 KeyedVector<String8, AaptSymbolEntry> mSymbols;
502 DefaultKeyedVector<String8, sp<AaptSymbols> > mNestedSymbols;
503 AaptSymbolEntry mDefSymbol;
504 };
505
506 class ResourceTypeSet : public RefBase,
507 public KeyedVector<String8,sp<AaptGroup> >
508 {
509 public:
510 ResourceTypeSet();
511 };
512
513 // Storage for lists of fully qualified paths for
514 // resources encountered during slurping.
515 class FilePathStore : public RefBase,
516 public Vector<String8>
517 {
518 public:
519 FilePathStore();
520 };
521
522 /**
523 * Asset hierarchy being operated on.
524 */
525 class AaptAssets : public AaptDir
526 {
527 public:
528 AaptAssets();
529 virtual ~AaptAssets() { delete mRes; }
530
531 const String8& getPackage() const { return mPackage; }
532 void setPackage(const String8& package) {
533 mPackage = package;
534 mSymbolsPrivatePackage = package;
535 mHavePrivateSymbols = false;
536 }
537
538 const SortedVector<AaptGroupEntry>& getGroupEntries() const;
539
540 virtual status_t addFile(const String8& name, const sp<AaptGroup>& file);
541
542 sp<AaptFile> addFile(const String8& filePath,
543 const AaptGroupEntry& entry,
544 const String8& srcDir,
545 sp<AaptGroup>* outGroup,
546 const String8& resType);
547
548 void addResource(const String8& leafName,
549 const String8& path,
550 const sp<AaptFile>& file,
551 const String8& resType);
552
553 void addGroupEntry(const AaptGroupEntry& entry) { mGroupEntries.add(entry); }
554
555 ssize_t slurpFromArgs(Bundle* bundle);
556
557 sp<AaptSymbols> getSymbolsFor(const String8& name);
558
559 sp<AaptSymbols> getJavaSymbolsFor(const String8& name);
560
561 status_t applyJavaSymbols();
562
563 const DefaultKeyedVector<String8, sp<AaptSymbols> >& getSymbols() const { return mSymbols; }
564
565 String8 getSymbolsPrivatePackage() const { return mSymbolsPrivatePackage; }
566 void setSymbolsPrivatePackage(const String8& pkg) {
567 mSymbolsPrivatePackage = pkg;
568 mHavePrivateSymbols = mSymbolsPrivatePackage != mPackage;
569 }
570
571 bool havePrivateSymbols() const { return mHavePrivateSymbols; }
572
573 bool isJavaSymbol(const AaptSymbolEntry& sym, bool includePrivate) const;
574
575 status_t buildIncludedResources(Bundle* bundle);
576 status_t addIncludedResources(const sp<AaptFile>& file);
577 const ResTable& getIncludedResources() const;
578
579 void print(const String8& prefix) const;
580
581 inline const Vector<sp<AaptDir> >& resDirs() const { return mResDirs; }
582 sp<AaptDir> resDir(const String8& name) const;
583
584 inline sp<AaptAssets> getOverlay() { return mOverlay; }
585 inline void setOverlay(sp<AaptAssets>& overlay) { mOverlay = overlay; }
586
587 inline KeyedVector<String8, sp<ResourceTypeSet> >* getResources() { return mRes; }
588 inline void
589 setResources(KeyedVector<String8, sp<ResourceTypeSet> >* res) { delete mRes; mRes = res; }
590
591 inline sp<FilePathStore>& getFullResPaths() { return mFullResPaths; }
592 inline void
593 setFullResPaths(sp<FilePathStore>& res) { mFullResPaths = res; }
594
595 inline sp<FilePathStore>& getFullAssetPaths() { return mFullAssetPaths; }
596 inline void
597 setFullAssetPaths(sp<FilePathStore>& res) { mFullAssetPaths = res; }
598
599 private:
600 virtual ssize_t slurpFullTree(Bundle* bundle,
601 const String8& srcDir,
602 const AaptGroupEntry& kind,
603 const String8& resType,
604 sp<FilePathStore>& fullResPaths);
605
606 ssize_t slurpResourceTree(Bundle* bundle, const String8& srcDir);
607 ssize_t slurpResourceZip(Bundle* bundle, const char* filename);
608
609 status_t filter(Bundle* bundle);
610
611 String8 mPackage;
612 SortedVector<AaptGroupEntry> mGroupEntries;
613 DefaultKeyedVector<String8, sp<AaptSymbols> > mSymbols;
614 DefaultKeyedVector<String8, sp<AaptSymbols> > mJavaSymbols;
615 String8 mSymbolsPrivatePackage;
616 bool mHavePrivateSymbols;
617
618 Vector<sp<AaptDir> > mResDirs;
619
620 bool mChanged;
621
622 bool mHaveIncludedAssets;
623 AssetManager mIncludedAssets;
624
625 sp<AaptAssets> mOverlay;
626 KeyedVector<String8, sp<ResourceTypeSet> >* mRes;
627
628 sp<FilePathStore> mFullResPaths;
629 sp<FilePathStore> mFullAssetPaths;
630 };
631
632 #endif // __AAPT_ASSETS_H
633