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