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