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