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