AaptAssets.h revision 1644c6d7f4931d0b4fe7ea77c63b016af01a46d3
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
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 */
60struct AaptGroupEntry
61{
62public:
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
112private:
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
138inline int compare_type(const AaptGroupEntry& lhs, const AaptGroupEntry& rhs)
139{
140    return lhs.compare(rhs);
141}
142
143inline int strictly_order_type(const AaptGroupEntry& lhs, const AaptGroupEntry& rhs)
144{
145    return compare_type(lhs, rhs) < 0;
146}
147
148class AaptGroup;
149class FilePathStore;
150
151/**
152 * A single asset file we know about.
153 */
154class AaptFile : public RefBase
155{
156public:
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; }
199private:
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 */
216class AaptGroup : public RefBase
217{
218public:
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
238private:
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 */
249class AaptDir : public RefBase
250{
251public:
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
291private:
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 */
314class AaptSymbolEntry
315{
316public:
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 */
370class AaptSymbols : public RefBase
371{
372public:
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
467private:
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
499class ResourceTypeSet : public RefBase,
500                        public KeyedVector<String8,sp<AaptGroup> >
501{
502public:
503    ResourceTypeSet();
504};
505
506// Storage for lists of fully qualified paths for
507// resources encountered during slurping.
508class FilePathStore : public RefBase,
509                      public Vector<String8>
510{
511public:
512    FilePathStore();
513};
514
515/**
516 * Asset hierarchy being operated on.
517 */
518class AaptAssets : public AaptDir
519{
520public:
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
592private:
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
627