AaptAssets.h revision 6c997a9e880e08c354ffd809bd62df9e25e9c4d4
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), typeCode(TYPE_UNKNOWN)
319    {
320    }
321    AaptSymbolEntry(const String8& _name)
322        : name(_name), isPublic(false), typeCode(TYPE_UNKNOWN)
323    {
324    }
325    AaptSymbolEntry(const AaptSymbolEntry& o)
326        : name(o.name), sourcePos(o.sourcePos), isPublic(o.isPublic)
327        , 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        comment = o.comment;
336        typeComment = o.typeComment;
337        typeCode = o.typeCode;
338        int32Val = o.int32Val;
339        stringVal = o.stringVal;
340        return *this;
341    }
342
343    const String8 name;
344
345    SourcePos sourcePos;
346    bool isPublic;
347
348    String16 comment;
349    String16 typeComment;
350
351    enum {
352        TYPE_UNKNOWN = 0,
353        TYPE_INT32,
354        TYPE_STRING
355    };
356
357    int typeCode;
358
359    // Value.  May be one of these.
360    int32_t int32Val;
361    String8 stringVal;
362};
363
364/**
365 * A group of related symbols (such as indices into a string block)
366 * that have been generated from the assets.
367 */
368class AaptSymbols : public RefBase
369{
370public:
371    AaptSymbols() { }
372    virtual ~AaptSymbols() { }
373
374    status_t addSymbol(const String8& name, int32_t value, const SourcePos& pos) {
375        if (!check_valid_symbol_name(name, pos, "symbol")) {
376            return BAD_VALUE;
377        }
378        AaptSymbolEntry& sym = edit_symbol(name, &pos);
379        sym.typeCode = AaptSymbolEntry::TYPE_INT32;
380        sym.int32Val = value;
381        return NO_ERROR;
382    }
383
384    status_t addStringSymbol(const String8& name, const String8& value,
385            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_STRING;
391        sym.stringVal = value;
392        return NO_ERROR;
393    }
394
395    status_t makeSymbolPublic(const String8& name, const SourcePos& pos) {
396        if (!check_valid_symbol_name(name, pos, "symbol")) {
397            return BAD_VALUE;
398        }
399        AaptSymbolEntry& sym = edit_symbol(name, &pos);
400        sym.isPublic = true;
401        return NO_ERROR;
402    }
403
404    void appendComment(const String8& name, const String16& comment, const SourcePos& pos) {
405        if (comment.size() <= 0) {
406            return;
407        }
408        AaptSymbolEntry& sym = edit_symbol(name, &pos);
409        if (sym.comment.size() == 0) {
410            sym.comment = comment;
411        } else {
412            sym.comment.append(String16("\n"));
413            sym.comment.append(comment);
414        }
415    }
416
417    void appendTypeComment(const String8& name, const String16& comment) {
418        if (comment.size() <= 0) {
419            return;
420        }
421        AaptSymbolEntry& sym = edit_symbol(name, NULL);
422        if (sym.typeComment.size() == 0) {
423            sym.typeComment = comment;
424        } else {
425            sym.typeComment.append(String16("\n"));
426            sym.typeComment.append(comment);
427        }
428    }
429
430    sp<AaptSymbols> addNestedSymbol(const String8& name, const SourcePos& pos) {
431        if (!check_valid_symbol_name(name, pos, "nested symbol")) {
432            return NULL;
433        }
434
435        sp<AaptSymbols> sym = mNestedSymbols.valueFor(name);
436        if (sym == NULL) {
437            sym = new AaptSymbols();
438            mNestedSymbols.add(name, sym);
439        }
440
441        return sym;
442    }
443
444    const KeyedVector<String8, AaptSymbolEntry>& getSymbols() const
445        { return mSymbols; }
446    const DefaultKeyedVector<String8, sp<AaptSymbols> >& getNestedSymbols() const
447        { return mNestedSymbols; }
448
449    const String16& getComment(const String8& name) const
450        { return get_symbol(name).comment; }
451    const String16& getTypeComment(const String8& name) const
452        { return get_symbol(name).typeComment; }
453
454private:
455    bool check_valid_symbol_name(const String8& symbol, const SourcePos& pos, const char* label) {
456        if (valid_symbol_name(symbol)) {
457            return true;
458        }
459        pos.error("invalid %s: '%s'\n", label, symbol.string());
460        return false;
461    }
462    AaptSymbolEntry& edit_symbol(const String8& symbol, const SourcePos* pos) {
463        ssize_t i = mSymbols.indexOfKey(symbol);
464        if (i < 0) {
465            i = mSymbols.add(symbol, AaptSymbolEntry(symbol));
466        }
467        AaptSymbolEntry& sym = mSymbols.editValueAt(i);
468        if (pos != NULL && sym.sourcePos.line < 0) {
469            sym.sourcePos = *pos;
470        }
471        return sym;
472    }
473    const AaptSymbolEntry& get_symbol(const String8& symbol) const {
474        ssize_t i = mSymbols.indexOfKey(symbol);
475        if (i >= 0) {
476            return mSymbols.valueAt(i);
477        }
478        return mDefSymbol;
479    }
480
481    KeyedVector<String8, AaptSymbolEntry>           mSymbols;
482    DefaultKeyedVector<String8, sp<AaptSymbols> >   mNestedSymbols;
483    AaptSymbolEntry                                 mDefSymbol;
484};
485
486class ResourceTypeSet : public RefBase,
487                        public KeyedVector<String8,sp<AaptGroup> >
488{
489public:
490    ResourceTypeSet();
491};
492
493// Storage for lists of fully qualified paths for
494// resources encountered during slurping.
495class FilePathStore : public RefBase,
496                      public Vector<String8>
497{
498public:
499    FilePathStore();
500};
501
502/**
503 * Asset hierarchy being operated on.
504 */
505class AaptAssets : public AaptDir
506{
507public:
508    AaptAssets();
509    virtual ~AaptAssets() { delete mRes; }
510
511    const String8& getPackage() const { return mPackage; }
512    void setPackage(const String8& package) { mPackage = package; mSymbolsPrivatePackage = package; }
513
514    const SortedVector<AaptGroupEntry>& getGroupEntries() const;
515
516    virtual status_t addFile(const String8& name, const sp<AaptGroup>& file);
517
518    sp<AaptFile> addFile(const String8& filePath,
519                         const AaptGroupEntry& entry,
520                         const String8& srcDir,
521                         sp<AaptGroup>* outGroup,
522                         const String8& resType);
523
524    void addResource(const String8& leafName,
525                     const String8& path,
526                     const sp<AaptFile>& file,
527                     const String8& resType);
528
529    void addGroupEntry(const AaptGroupEntry& entry) { mGroupEntries.add(entry); }
530
531    ssize_t slurpFromArgs(Bundle* bundle);
532
533    sp<AaptSymbols> getSymbolsFor(const String8& name);
534
535    const DefaultKeyedVector<String8, sp<AaptSymbols> >& getSymbols() const { return mSymbols; }
536
537    String8 getSymbolsPrivatePackage() const { return mSymbolsPrivatePackage; }
538    void setSymbolsPrivatePackage(const String8& pkg) { mSymbolsPrivatePackage = pkg; }
539
540    status_t buildIncludedResources(Bundle* bundle);
541    status_t addIncludedResources(const sp<AaptFile>& file);
542    const ResTable& getIncludedResources() const;
543
544    void print(const String8& prefix) const;
545
546    inline const Vector<sp<AaptDir> >& resDirs() const { return mResDirs; }
547    sp<AaptDir> resDir(const String8& name) const;
548
549    inline sp<AaptAssets> getOverlay() { return mOverlay; }
550    inline void setOverlay(sp<AaptAssets>& overlay) { mOverlay = overlay; }
551
552    inline KeyedVector<String8, sp<ResourceTypeSet> >* getResources() { return mRes; }
553    inline void
554        setResources(KeyedVector<String8, sp<ResourceTypeSet> >* res) { delete mRes; mRes = res; }
555
556    inline sp<FilePathStore>& getFullResPaths() { return mFullResPaths; }
557    inline void
558        setFullResPaths(sp<FilePathStore>& res) { mFullResPaths = res; }
559
560    inline sp<FilePathStore>& getFullAssetPaths() { return mFullAssetPaths; }
561    inline void
562        setFullAssetPaths(sp<FilePathStore>& res) { mFullAssetPaths = res; }
563
564private:
565    virtual ssize_t slurpFullTree(Bundle* bundle,
566                                  const String8& srcDir,
567                                  const AaptGroupEntry& kind,
568                                  const String8& resType,
569                                  sp<FilePathStore>& fullResPaths);
570
571    ssize_t slurpResourceTree(Bundle* bundle, const String8& srcDir);
572    ssize_t slurpResourceZip(Bundle* bundle, const char* filename);
573
574    status_t filter(Bundle* bundle);
575
576    String8 mPackage;
577    SortedVector<AaptGroupEntry> mGroupEntries;
578    DefaultKeyedVector<String8, sp<AaptSymbols> > mSymbols;
579    String8 mSymbolsPrivatePackage;
580
581    Vector<sp<AaptDir> > mResDirs;
582
583    bool mChanged;
584
585    bool mHaveIncludedAssets;
586    AssetManager mIncludedAssets;
587
588    sp<AaptAssets> mOverlay;
589    KeyedVector<String8, sp<ResourceTypeSet> >* mRes;
590
591    sp<FilePathStore> mFullResPaths;
592    sp<FilePathStore> mFullAssetPaths;
593};
594
595#endif // __AAPT_ASSETS_H
596
597