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