1 // 2 // Copyright 2006 The Android Open Source Project 3 // 4 // Build resource files from raw assets. 5 // 6 7 #ifndef RESOURCE_TABLE_H 8 #define RESOURCE_TABLE_H 9 10 #include <map> 11 #include <queue> 12 #include <set> 13 14 #include "ConfigDescription.h" 15 #include "ResourceFilter.h" 16 #include "SourcePos.h" 17 #include "StringPool.h" 18 #include "Symbol.h" 19 20 class XMLNode; 21 class ResourceTable; 22 23 enum { 24 XML_COMPILE_STRIP_COMMENTS = 1<<0, 25 XML_COMPILE_ASSIGN_ATTRIBUTE_IDS = 1<<1, 26 XML_COMPILE_COMPACT_WHITESPACE = 1<<2, 27 XML_COMPILE_STRIP_WHITESPACE = 1<<3, 28 XML_COMPILE_STRIP_RAW_VALUES = 1<<4, 29 XML_COMPILE_UTF8 = 1<<5, 30 31 XML_COMPILE_STANDARD_RESOURCE = 32 XML_COMPILE_STRIP_COMMENTS | XML_COMPILE_ASSIGN_ATTRIBUTE_IDS 33 | XML_COMPILE_STRIP_WHITESPACE | XML_COMPILE_STRIP_RAW_VALUES 34 }; 35 36 status_t compileXmlFile(const Bundle* bundle, 37 const sp<AaptAssets>& assets, 38 const String16& resourceName, 39 const sp<AaptFile>& target, 40 ResourceTable* table, 41 int options = XML_COMPILE_STANDARD_RESOURCE); 42 43 status_t compileXmlFile(const Bundle* bundle, 44 const sp<AaptAssets>& assets, 45 const String16& resourceName, 46 const sp<AaptFile>& target, 47 const sp<AaptFile>& outTarget, 48 ResourceTable* table, 49 int options = XML_COMPILE_STANDARD_RESOURCE); 50 51 status_t compileXmlFile(const Bundle* bundle, 52 const sp<AaptAssets>& assets, 53 const String16& resourceName, 54 const sp<XMLNode>& xmlTree, 55 const sp<AaptFile>& target, 56 ResourceTable* table, 57 int options = XML_COMPILE_STANDARD_RESOURCE); 58 59 status_t compileResourceFile(Bundle* bundle, 60 const sp<AaptAssets>& assets, 61 const sp<AaptFile>& in, 62 const ResTable_config& defParams, 63 const bool overwrite, 64 ResourceTable* outTable); 65 66 struct AccessorCookie 67 { 68 SourcePos sourcePos; 69 String8 attr; 70 String8 value; 71 AccessorCookieAccessorCookie72 AccessorCookie(const SourcePos&p, const String8& a, const String8& v) 73 :sourcePos(p), 74 attr(a), 75 value(v) 76 { 77 } 78 }; 79 80 // Holds the necessary information to compile the 81 // resource. 82 struct CompileResourceWorkItem { 83 String16 resourceName; 84 String8 resPath; 85 sp<AaptFile> file; 86 }; 87 88 class ResourceTable : public ResTable::Accessor 89 { 90 public: 91 // The type of package to build. 92 enum PackageType { 93 App, 94 System, 95 SharedLibrary, 96 AppFeature 97 }; 98 99 class Package; 100 class Type; 101 class Entry; 102 class ConfigList; 103 104 /** 105 * Exposed for testing. Determines whether a versioned resource should be generated 106 * based on the other available configurations for that resource. 107 */ 108 static bool shouldGenerateVersionedResource(const sp<ConfigList>& configList, 109 const ConfigDescription& sourceConfig, 110 const int sdkVersionToGenerate); 111 112 ResourceTable(Bundle* bundle, const String16& assetsPackage, PackageType type); 113 getAssetsPackage()114 const String16& getAssetsPackage() const { 115 return mAssetsPackage; 116 } 117 118 /** 119 * Returns the queue of resources that need to be compiled. 120 * This is only used for resources that have been generated 121 * during the compilation phase. If they were just added 122 * to the AaptAssets, then they may be skipped over 123 * and would mess up iteration order for the existing 124 * resources. 125 */ getWorkQueue()126 std::queue<CompileResourceWorkItem>& getWorkQueue() { 127 return mWorkQueue; 128 } 129 130 status_t addIncludedResources(Bundle* bundle, const sp<AaptAssets>& assets); 131 132 status_t addPublic(const SourcePos& pos, 133 const String16& package, 134 const String16& type, 135 const String16& name, 136 const uint32_t ident); 137 138 status_t addEntry(const SourcePos& pos, 139 const String16& package, 140 const String16& type, 141 const String16& name, 142 const String16& value, 143 const Vector<StringPool::entry_style_span>* style = NULL, 144 const ResTable_config* params = NULL, 145 const bool doSetIndex = false, 146 const int32_t format = ResTable_map::TYPE_ANY, 147 const bool overwrite = false); 148 149 status_t startBag(const SourcePos& pos, 150 const String16& package, 151 const String16& type, 152 const String16& name, 153 const String16& bagParent, 154 const ResTable_config* params = NULL, 155 bool overlay = false, 156 bool replace = false, 157 bool isId = false); 158 159 status_t addBag(const SourcePos& pos, 160 const String16& package, 161 const String16& type, 162 const String16& name, 163 const String16& bagParent, 164 const String16& bagKey, 165 const String16& value, 166 const Vector<StringPool::entry_style_span>* style = NULL, 167 const ResTable_config* params = NULL, 168 bool replace = false, 169 bool isId = false, 170 const int32_t format = ResTable_map::TYPE_ANY); 171 172 bool hasBagOrEntry(const String16& package, 173 const String16& type, 174 const String16& name) const; 175 176 bool hasBagOrEntry(const String16& package, 177 const String16& type, 178 const String16& name, 179 const ResTable_config& config) const; 180 181 bool hasBagOrEntry(const String16& ref, 182 const String16* defType = NULL, 183 const String16* defPackage = NULL); 184 185 bool appendComment(const String16& package, 186 const String16& type, 187 const String16& name, 188 const String16& comment, 189 bool onlyIfEmpty = false); 190 191 bool appendTypeComment(const String16& package, 192 const String16& type, 193 const String16& name, 194 const String16& comment); 195 196 void canAddEntry(const SourcePos& pos, 197 const String16& package, const String16& type, const String16& name); 198 199 size_t size() const; 200 size_t numLocalResources() const; 201 bool hasResources() const; 202 203 status_t modifyForCompat(const Bundle* bundle); 204 status_t modifyForCompat(const Bundle* bundle, 205 const String16& resourceName, 206 const sp<AaptFile>& file, 207 const sp<XMLNode>& root); 208 209 sp<AaptFile> flatten(Bundle* bundle, const sp<const ResourceFilter>& filter, 210 const bool isBase); 211 makeResId(uint32_t packageId,uint32_t typeId,uint32_t nameId)212 static inline uint32_t makeResId(uint32_t packageId, 213 uint32_t typeId, 214 uint32_t nameId) 215 { 216 return nameId | (typeId<<16) | (packageId<<24); 217 } 218 219 static inline uint32_t getResId(const sp<Package>& p, 220 const sp<Type>& t, 221 uint32_t nameId); 222 223 uint32_t getResId(const String16& package, 224 const String16& type, 225 const String16& name, 226 bool onlyPublic = true) const; 227 228 uint32_t getResId(const String16& ref, 229 const String16* defType = NULL, 230 const String16* defPackage = NULL, 231 const char** outErrorMsg = NULL, 232 bool onlyPublic = true) const; 233 234 static bool isValidResourceName(const String16& s); 235 236 bool stringToValue(Res_value* outValue, StringPool* pool, 237 const String16& str, 238 bool preserveSpaces, bool coerceType, 239 uint32_t attrID, 240 const Vector<StringPool::entry_style_span>* style = NULL, 241 String16* outStr = NULL, void* accessorCookie = NULL, 242 uint32_t attrType = ResTable_map::TYPE_ANY, 243 const String8* configTypeName = NULL, 244 const ConfigDescription* config = NULL); 245 246 status_t assignResourceIds(); 247 status_t addSymbols(const sp<AaptSymbols>& outSymbols = NULL, 248 bool skipSymbolsWithoutDefaultLocalization = false); 249 void addLocalization(const String16& name, const String8& locale, const SourcePos& src); 250 void addDefaultLocalization(const String16& name); 251 status_t validateLocalizations(void); 252 253 status_t flatten(Bundle* bundle, const sp<const ResourceFilter>& filter, 254 const sp<AaptFile>& dest, const bool isBase); 255 status_t flattenLibraryTable(const sp<AaptFile>& dest, const Vector<sp<Package> >& libs); 256 257 void writePublicDefinitions(const String16& package, FILE* fp); 258 259 virtual uint32_t getCustomResource(const String16& package, 260 const String16& type, 261 const String16& name) const; 262 virtual uint32_t getCustomResourceWithCreation(const String16& package, 263 const String16& type, 264 const String16& name, 265 const bool createIfNeeded); 266 virtual uint32_t getRemappedPackage(uint32_t origPackage) const; 267 virtual bool getAttributeType(uint32_t attrID, uint32_t* outType); 268 virtual bool getAttributeMin(uint32_t attrID, uint32_t* outMin); 269 virtual bool getAttributeMax(uint32_t attrID, uint32_t* outMax); 270 virtual bool getAttributeKeys(uint32_t attrID, Vector<String16>* outKeys); 271 virtual bool getAttributeEnum(uint32_t attrID, 272 const char16_t* name, size_t nameLen, 273 Res_value* outValue); 274 virtual bool getAttributeFlags(uint32_t attrID, 275 const char16_t* name, size_t nameLen, 276 Res_value* outValue); 277 virtual uint32_t getAttributeL10N(uint32_t attrID); 278 279 virtual bool getLocalizationSetting(); 280 virtual void reportError(void* accessorCookie, const char* fmt, ...); 281 setCurrentXmlPos(const SourcePos & pos)282 void setCurrentXmlPos(const SourcePos& pos) { mCurrentXmlPos = pos; } 283 284 class Item { 285 public: Item()286 Item() : isId(false), format(ResTable_map::TYPE_ANY), bagKeyId(0), evaluating(false) 287 { memset(&parsedValue, 0, sizeof(parsedValue)); } 288 Item(const SourcePos& pos, 289 bool _isId, 290 const String16& _value, 291 const Vector<StringPool::entry_style_span>* _style = NULL, 292 int32_t format = ResTable_map::TYPE_ANY); Item(const Item & o)293 Item(const Item& o) : sourcePos(o.sourcePos), 294 isId(o.isId), value(o.value), style(o.style), 295 format(o.format), bagKeyId(o.bagKeyId), evaluating(false) { 296 memset(&parsedValue, 0, sizeof(parsedValue)); 297 } ~Item()298 ~Item() { } 299 300 Item& operator=(const Item& o) { 301 sourcePos = o.sourcePos; 302 isId = o.isId; 303 value = o.value; 304 style = o.style; 305 format = o.format; 306 bagKeyId = o.bagKeyId; 307 parsedValue = o.parsedValue; 308 return *this; 309 } 310 311 SourcePos sourcePos; 312 mutable bool isId; 313 String16 value; 314 Vector<StringPool::entry_style_span> style; 315 int32_t format; 316 uint32_t bagKeyId; 317 mutable bool evaluating; 318 Res_value parsedValue; 319 }; 320 321 class Entry : public RefBase { 322 public: Entry(const String16 & name,const SourcePos & pos)323 Entry(const String16& name, const SourcePos& pos) 324 : mName(name), mType(TYPE_UNKNOWN), 325 mItemFormat(ResTable_map::TYPE_ANY), mNameIndex(-1), mPos(pos) 326 { } 327 328 Entry(const Entry& entry); 329 Entry& operator=(const Entry& entry); 330 ~Entry()331 virtual ~Entry() { } 332 333 enum type { 334 TYPE_UNKNOWN = 0, 335 TYPE_ITEM, 336 TYPE_BAG 337 }; 338 getName()339 String16 getName() const { return mName; } getType()340 type getType() const { return mType; } 341 setParent(const String16 & parent)342 void setParent(const String16& parent) { mParent = parent; } getParent()343 String16 getParent() const { return mParent; } 344 345 status_t makeItABag(const SourcePos& sourcePos); 346 347 status_t emptyBag(const SourcePos& sourcePos); 348 349 status_t setItem(const SourcePos& pos, 350 const String16& value, 351 const Vector<StringPool::entry_style_span>* style = NULL, 352 int32_t format = ResTable_map::TYPE_ANY, 353 const bool overwrite = false); 354 355 status_t addToBag(const SourcePos& pos, 356 const String16& key, const String16& value, 357 const Vector<StringPool::entry_style_span>* style = NULL, 358 bool replace=false, bool isId = false, 359 int32_t format = ResTable_map::TYPE_ANY); 360 361 status_t removeFromBag(const String16& key); 362 363 // Index of the entry's name string in the key pool. getNameIndex()364 int32_t getNameIndex() const { return mNameIndex; } setNameIndex(int32_t index)365 void setNameIndex(int32_t index) { mNameIndex = index; } 366 getItem()367 const Item* getItem() const { return mType == TYPE_ITEM ? &mItem : NULL; } getBag()368 const KeyedVector<String16, Item>& getBag() const { return mBag; } 369 370 status_t generateAttributes(ResourceTable* table, 371 const String16& package); 372 373 status_t assignResourceIds(ResourceTable* table, 374 const String16& package); 375 376 status_t prepareFlatten(StringPool* strings, ResourceTable* table, 377 const String8* configTypeName, const ConfigDescription* config); 378 379 status_t remapStringValue(StringPool* strings); 380 381 ssize_t flatten(Bundle*, const sp<AaptFile>& data, bool isPublic); 382 getPos()383 const SourcePos& getPos() const { return mPos; } 384 385 private: 386 String16 mName; 387 String16 mParent; 388 type mType; 389 Item mItem; 390 int32_t mItemFormat; 391 KeyedVector<String16, Item> mBag; 392 int32_t mNameIndex; 393 uint32_t mParentId; 394 SourcePos mPos; 395 }; 396 397 class ConfigList : public RefBase { 398 public: ConfigList(const String16 & name,const SourcePos & pos)399 ConfigList(const String16& name, const SourcePos& pos) 400 : mName(name), mPos(pos), mPublic(false), mEntryIndex(-1) { } ~ConfigList()401 virtual ~ConfigList() { } 402 getName()403 String16 getName() const { return mName; } getPos()404 const SourcePos& getPos() const { return mPos; } 405 406 void appendComment(const String16& comment, bool onlyIfEmpty = false); getComment()407 const String16& getComment() const { return mComment; } 408 409 void appendTypeComment(const String16& comment); getTypeComment()410 const String16& getTypeComment() const { return mTypeComment; } 411 412 // Index of this entry in its Type. getEntryIndex()413 int32_t getEntryIndex() const { return mEntryIndex; } setEntryIndex(int32_t index)414 void setEntryIndex(int32_t index) { mEntryIndex = index; } 415 setPublic(bool pub)416 void setPublic(bool pub) { mPublic = pub; } getPublic()417 bool getPublic() const { return mPublic; } setPublicSourcePos(const SourcePos & pos)418 void setPublicSourcePos(const SourcePos& pos) { mPublicSourcePos = pos; } getPublicSourcePos()419 const SourcePos& getPublicSourcePos() { return mPublicSourcePos; } 420 addEntry(const ResTable_config & config,const sp<Entry> & entry)421 void addEntry(const ResTable_config& config, const sp<Entry>& entry) { 422 mEntries.add(config, entry); 423 } 424 getEntries()425 const DefaultKeyedVector<ConfigDescription, sp<Entry> >& getEntries() const { return mEntries; } 426 private: 427 const String16 mName; 428 const SourcePos mPos; 429 String16 mComment; 430 String16 mTypeComment; 431 bool mPublic; 432 SourcePos mPublicSourcePos; 433 int32_t mEntryIndex; 434 DefaultKeyedVector<ConfigDescription, sp<Entry> > mEntries; 435 }; 436 437 class Public { 438 public: Public()439 Public() : sourcePos(), ident(0) { } Public(const SourcePos & pos,const String16 & _comment,uint32_t _ident)440 Public(const SourcePos& pos, 441 const String16& _comment, 442 uint32_t _ident) 443 : sourcePos(pos), 444 comment(_comment), ident(_ident) { } Public(const Public & o)445 Public(const Public& o) : sourcePos(o.sourcePos), 446 comment(o.comment), ident(o.ident) { } ~Public()447 ~Public() { } 448 449 Public& operator=(const Public& o) { 450 sourcePos = o.sourcePos; 451 comment = o.comment; 452 ident = o.ident; 453 return *this; 454 } 455 456 SourcePos sourcePos; 457 String16 comment; 458 uint32_t ident; 459 }; 460 461 class Type : public RefBase { 462 public: Type(const String16 & name,const SourcePos & pos)463 Type(const String16& name, const SourcePos& pos) 464 : mName(name), mFirstPublicSourcePos(NULL), mPublicIndex(-1), mIndex(-1), mPos(pos) 465 { } ~Type()466 virtual ~Type() { delete mFirstPublicSourcePos; } 467 468 status_t addPublic(const SourcePos& pos, 469 const String16& name, 470 const uint32_t ident); 471 472 void canAddEntry(const String16& name); 473 getName()474 String16 getName() const { return mName; } 475 sp<Entry> getEntry(const String16& entry, 476 const SourcePos& pos, 477 const ResTable_config* config = NULL, 478 bool doSetIndex = false, 479 bool overlay = false, 480 bool autoAddOverlay = false); 481 isPublic(const String16 & entry)482 bool isPublic(const String16& entry) const { 483 return mPublic.indexOfKey(entry) >= 0; 484 } 485 486 sp<ConfigList> removeEntry(const String16& entry); 487 488 SortedVector<ConfigDescription> getUniqueConfigs() const; 489 getFirstPublicSourcePos()490 const SourcePos& getFirstPublicSourcePos() const { return *mFirstPublicSourcePos; } 491 getPublicIndex()492 int32_t getPublicIndex() const { return mPublicIndex; } 493 getIndex()494 int32_t getIndex() const { return mIndex; } setIndex(int32_t index)495 void setIndex(int32_t index) { mIndex = index; } 496 497 status_t applyPublicEntryOrder(); 498 getConfigs()499 const DefaultKeyedVector<String16, sp<ConfigList> >& getConfigs() const { return mConfigs; } getOrderedConfigs()500 const Vector<sp<ConfigList> >& getOrderedConfigs() const { return mOrderedConfigs; } getCanAddEntries()501 const SortedVector<String16>& getCanAddEntries() const { return mCanAddEntries; } 502 getPos()503 const SourcePos& getPos() const { return mPos; } 504 505 private: 506 String16 mName; 507 SourcePos* mFirstPublicSourcePos; 508 DefaultKeyedVector<String16, Public> mPublic; 509 DefaultKeyedVector<String16, sp<ConfigList> > mConfigs; 510 Vector<sp<ConfigList> > mOrderedConfigs; 511 SortedVector<String16> mCanAddEntries; 512 int32_t mPublicIndex; 513 int32_t mIndex; 514 SourcePos mPos; 515 }; 516 517 class Package : public RefBase { 518 public: 519 Package(const String16& name, size_t packageId); ~Package()520 virtual ~Package() { } 521 getName()522 String16 getName() const { return mName; } 523 sp<Type> getType(const String16& type, 524 const SourcePos& pos, 525 bool doSetIndex = false); 526 getAssignedId()527 size_t getAssignedId() const { return mPackageId; } 528 getTypeStrings()529 const ResStringPool& getTypeStrings() const { return mTypeStrings; } indexOfTypeString(const String16 & s)530 uint32_t indexOfTypeString(const String16& s) const { return mTypeStringsMapping.valueFor(s); } getTypeStringsData()531 const sp<AaptFile> getTypeStringsData() const { return mTypeStringsData; } 532 status_t setTypeStrings(const sp<AaptFile>& data); 533 getKeyStrings()534 const ResStringPool& getKeyStrings() const { return mKeyStrings; } indexOfKeyString(const String16 & s)535 uint32_t indexOfKeyString(const String16& s) const { return mKeyStringsMapping.valueFor(s); } getKeyStringsData()536 const sp<AaptFile> getKeyStringsData() const { return mKeyStringsData; } 537 status_t setKeyStrings(const sp<AaptFile>& data); 538 539 status_t applyPublicTypeOrder(); 540 getTypes()541 const DefaultKeyedVector<String16, sp<Type> >& getTypes() const { return mTypes; } getOrderedTypes()542 const Vector<sp<Type> >& getOrderedTypes() const { return mOrderedTypes; } 543 544 void movePrivateAttrs(); 545 546 private: 547 status_t setStrings(const sp<AaptFile>& data, 548 ResStringPool* strings, 549 DefaultKeyedVector<String16, uint32_t>* mappings); 550 551 const String16 mName; 552 const size_t mPackageId; 553 DefaultKeyedVector<String16, sp<Type> > mTypes; 554 Vector<sp<Type> > mOrderedTypes; 555 sp<AaptFile> mTypeStringsData; 556 sp<AaptFile> mKeyStringsData; 557 ResStringPool mTypeStrings; 558 ResStringPool mKeyStrings; 559 DefaultKeyedVector<String16, uint32_t> mTypeStringsMapping; 560 DefaultKeyedVector<String16, uint32_t> mKeyStringsMapping; 561 }; 562 563 void getDensityVaryingResources(KeyedVector<Symbol, Vector<SymbolDefinition> >& resources); 564 565 private: 566 void writePublicDefinitions(const String16& package, FILE* fp, bool pub); 567 sp<Package> getPackage(const String16& package); 568 sp<Type> getType(const String16& package, 569 const String16& type, 570 const SourcePos& pos, 571 bool doSetIndex = false); 572 sp<Entry> getEntry(const String16& package, 573 const String16& type, 574 const String16& name, 575 const SourcePos& pos, 576 bool overlay, 577 const ResTable_config* config = NULL, 578 bool doSetIndex = false); 579 sp<const Entry> getEntry(uint32_t resID, 580 const ResTable_config* config = NULL) const; 581 sp<ConfigList> getConfigList(const String16& package, 582 const String16& type, 583 const String16& name) const; 584 const Item* getItem(uint32_t resID, uint32_t attrID) const; 585 bool getItemValue(uint32_t resID, uint32_t attrID, 586 Res_value* outValue); 587 int getPublicAttributeSdkLevel(uint32_t attrId) const; 588 589 590 String16 mAssetsPackage; 591 PackageType mPackageType; 592 sp<AaptAssets> mAssets; 593 uint32_t mTypeIdOffset; 594 DefaultKeyedVector<String16, sp<Package> > mPackages; 595 Vector<sp<Package> > mOrderedPackages; 596 size_t mNumLocal; 597 SourcePos mCurrentXmlPos; 598 Bundle* mBundle; 599 600 // key = string resource name, value = set of locales in which that name is defined 601 std::map<String16, std::map<String8, SourcePos>> mLocalizations; 602 // set of string resources names that have a default localization 603 std::set<String16> mHasDefaultLocalization; 604 std::queue<CompileResourceWorkItem> mWorkQueue; 605 }; 606 607 #endif 608