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