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