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