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