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