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