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