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 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:
     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 
    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 
    149 inline int compare_type(const AaptGroupEntry& lhs, const AaptGroupEntry& rhs)
    150 {
    151     return lhs.compare(rhs);
    152 }
    153 
    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:
    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; }
    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:
    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 
    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:
    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 
    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:
    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  */
    379 class AaptSymbols : public RefBase
    380 {
    381 public:
    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 
    465 private:
    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 
    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();
    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 
    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