AaptAssets.h revision e6b680364dd992907a8d2037685a2e500d188dfb
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
23using namespace android;
24
25bool valid_symbol_name(const String8& str);
26
27class AaptAssets;
28
29enum {
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
56enum {
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 */
71struct AaptGroupEntry
72{
73public:
74    AaptGroupEntry() : mParamsChanged(true) { }
75    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
121    const String8& getVersionString() const { return version; }
122
123private:
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
149inline int compare_type(const AaptGroupEntry& lhs, const AaptGroupEntry& rhs)
150{
151    return lhs.compare(rhs);
152}
153
154inline int strictly_order_type(const AaptGroupEntry& lhs, const AaptGroupEntry& rhs)
155{
156    return compare_type(lhs, rhs) < 0;
157}
158
159class AaptGroup;
160class FilePathStore;
161
162/**
163 * A single asset file we know about.
164 */
165class AaptFile : public RefBase
166{
167public:
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        }
180    virtual ~AaptFile() {
181        free(mData);
182    }
183
184    const String8& getPath() const { return mPath; }
185    const AaptGroupEntry& getGroupEntry() const { return mGroupEntry; }
186
187    // Data API.  If there is data attached to the file,
188    // getSourceFile() is not used.
189    bool hasData() const { return mData != NULL; }
190    const void* getData() const { return mData; }
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
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.
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.
208    int getCompressionMethod() const { return mCompression; }
209    void setCompressionMethod(int c) { mCompression = c; }
210private:
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 */
227class AaptGroup : public RefBase
228{
229public:
230    AaptGroup(const String8& leaf, const String8& path)
231        : mLeaf(leaf), mPath(path) { }
232    virtual ~AaptGroup() { }
233
234    const String8& getLeaf() const { return mLeaf; }
235
236    // Returns the relative path after the AaptGroupEntry dirs.
237    const String8& getPath() const { return mPath; }
238
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
249private:
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 */
260class AaptDir : public RefBase
261{
262public:
263    AaptDir(const String8& leaf, const String8& path)
264        : mLeaf(leaf), mPath(path) { }
265    virtual ~AaptDir() { }
266
267    const String8& getLeaf() const { return mLeaf; }
268
269    const String8& getPath() const { return mPath; }
270
271    const DefaultKeyedVector<String8, sp<AaptGroup> >& getFiles() const { return mFiles; }
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
302private:
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 */
325class AaptSymbolEntry
326{
327public:
328    AaptSymbolEntry()
329        : isPublic(false), typeCode(TYPE_UNKNOWN)
330    {
331    }
332    AaptSymbolEntry(const String8& _name)
333        : name(_name), isPublic(false), typeCode(TYPE_UNKNOWN)
334    {
335    }
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 */
379class AaptSymbols : public RefBase
380{
381public:
382    AaptSymbols() { }
383    virtual ~AaptSymbols() { }
384
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
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
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
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    const KeyedVector<String8, AaptSymbolEntry>& getSymbols() const
456        { return mSymbols; }
457    const DefaultKeyedVector<String8, sp<AaptSymbols> >& getNestedSymbols() const
458        { return mNestedSymbols; }
459
460    const String16& getComment(const String8& name) const
461        { return get_symbol(name).comment; }
462    const String16& getTypeComment(const String8& name) const
463        { return get_symbol(name).typeComment; }
464
465private:
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    }
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    }
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
497class ResourceTypeSet : public RefBase,
498                        public KeyedVector<String8,sp<AaptGroup> >
499{
500public:
501    ResourceTypeSet();
502};
503
504// Storage for lists of fully qualified paths for
505// resources encountered during slurping.
506class FilePathStore : public RefBase,
507                      public Vector<String8>
508{
509public:
510    FilePathStore();
511};
512
513/**
514 * Asset hierarchy being operated on.
515 */
516class AaptAssets : public AaptDir
517{
518public:
519    AaptAssets();
520    virtual ~AaptAssets() { delete mRes; }
521
522    const String8& getPackage() const { return mPackage; }
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
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
546    const DefaultKeyedVector<String8, sp<AaptSymbols> >& getSymbols() const { return mSymbols; }
547
548    String8 getSymbolsPrivatePackage() const { return mSymbolsPrivatePackage; }
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
557    inline const Vector<sp<AaptDir> >& resDirs() const { return mResDirs; }
558    sp<AaptDir> resDir(const String8& name) const;
559
560    inline sp<AaptAssets> getOverlay() { return mOverlay; }
561    inline void setOverlay(sp<AaptAssets>& overlay) { mOverlay = overlay; }
562
563    inline KeyedVector<String8, sp<ResourceTypeSet> >* getResources() { return mRes; }
564    inline void
565        setResources(KeyedVector<String8, sp<ResourceTypeSet> >* res) { delete mRes; mRes = res; }
566
567    inline sp<FilePathStore>& getFullResPaths() { return mFullResPaths; }
568    inline void
569        setFullResPaths(sp<FilePathStore>& res) { mFullResPaths = res; }
570
571    inline sp<FilePathStore>& getFullAssetPaths() { return mFullAssetPaths; }
572    inline void
573        setFullAssetPaths(sp<FilePathStore>& res) { mFullAssetPaths = res; }
574
575private:
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