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