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