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