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