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