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