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