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