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