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