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