| // | |
| // Copyright 2006 The Android Open Source Project | |
| // | |
| // Build resource files from raw assets. | |
| // | |
| #ifndef RESOURCE_TABLE_H | |
| #define RESOURCE_TABLE_H | |
| #include <map> | |
| #include <queue> | |
| #include <set> | |
| #include "ConfigDescription.h" | |
| #include "ResourceFilter.h" | |
| #include "SourcePos.h" | |
| #include "StringPool.h" | |
| #include "Symbol.h" | |
| class XMLNode; | |
| class ResourceTable; | |
| enum { | |
| XML_COMPILE_STRIP_COMMENTS = 1<<0, | |
| XML_COMPILE_ASSIGN_ATTRIBUTE_IDS = 1<<1, | |
| XML_COMPILE_PARSE_VALUES = 1 << 2, | |
| XML_COMPILE_COMPACT_WHITESPACE = 1<<3, | |
| XML_COMPILE_STRIP_WHITESPACE = 1<<4, | |
| XML_COMPILE_STRIP_RAW_VALUES = 1<<5, | |
| XML_COMPILE_UTF8 = 1<<6, | |
| XML_COMPILE_STANDARD_RESOURCE = | |
| XML_COMPILE_STRIP_COMMENTS | XML_COMPILE_ASSIGN_ATTRIBUTE_IDS | XML_COMPILE_PARSE_VALUES | |
| | XML_COMPILE_STRIP_WHITESPACE | XML_COMPILE_STRIP_RAW_VALUES | |
| }; | |
| status_t compileXmlFile(const Bundle* bundle, | |
| const sp<AaptAssets>& assets, | |
| const String16& resourceName, | |
| const sp<AaptFile>& target, | |
| ResourceTable* table, | |
| int options = XML_COMPILE_STANDARD_RESOURCE); | |
| status_t compileXmlFile(const Bundle* bundle, | |
| const sp<AaptAssets>& assets, | |
| const String16& resourceName, | |
| const sp<AaptFile>& target, | |
| const sp<AaptFile>& outTarget, | |
| ResourceTable* table, | |
| int options = XML_COMPILE_STANDARD_RESOURCE); | |
| status_t compileXmlFile(const Bundle* bundle, | |
| const sp<AaptAssets>& assets, | |
| const String16& resourceName, | |
| const sp<XMLNode>& xmlTree, | |
| const sp<AaptFile>& target, | |
| ResourceTable* table, | |
| int options = XML_COMPILE_STANDARD_RESOURCE); | |
| status_t compileResourceFile(Bundle* bundle, | |
| const sp<AaptAssets>& assets, | |
| const sp<AaptFile>& in, | |
| const ResTable_config& defParams, | |
| const bool overwrite, | |
| ResourceTable* outTable); | |
| struct AccessorCookie | |
| { | |
| SourcePos sourcePos; | |
| String8 attr; | |
| String8 value; | |
| AccessorCookie(const SourcePos&p, const String8& a, const String8& v) | |
| :sourcePos(p), | |
| attr(a), | |
| value(v) | |
| { | |
| } | |
| }; | |
| // Holds the necessary information to compile the | |
| // resource. | |
| struct CompileResourceWorkItem { | |
| String16 resourceName; | |
| String8 resPath; | |
| sp<AaptFile> file; | |
| sp<XMLNode> xmlRoot; | |
| bool needsCompiling = true; | |
| }; | |
| class ResourceTable : public ResTable::Accessor | |
| { | |
| public: | |
| // The type of package to build. | |
| enum PackageType { | |
| App, | |
| System, | |
| SharedLibrary, | |
| AppFeature | |
| }; | |
| class Package; | |
| class Type; | |
| class Entry; | |
| class ConfigList; | |
| /** | |
| * Exposed for testing. Determines whether a versioned resource should be generated | |
| * based on the other available configurations for that resource. | |
| */ | |
| static bool shouldGenerateVersionedResource(const sp<ConfigList>& configList, | |
| const ConfigDescription& sourceConfig, | |
| const int sdkVersionToGenerate); | |
| ResourceTable(Bundle* bundle, const String16& assetsPackage, PackageType type); | |
| const String16& getAssetsPackage() const { | |
| return mAssetsPackage; | |
| } | |
| /** | |
| * Returns the queue of resources that need to be compiled. | |
| * This is only used for resources that have been generated | |
| * during the compilation phase. If they were just added | |
| * to the AaptAssets, then they may be skipped over | |
| * and would mess up iteration order for the existing | |
| * resources. | |
| */ | |
| std::queue<CompileResourceWorkItem>& getWorkQueue() { | |
| return mWorkQueue; | |
| } | |
| status_t addIncludedResources(Bundle* bundle, const sp<AaptAssets>& assets); | |
| status_t addPublic(const SourcePos& pos, | |
| const String16& package, | |
| const String16& type, | |
| const String16& name, | |
| const uint32_t ident); | |
| status_t addEntry(const SourcePos& pos, | |
| const String16& package, | |
| const String16& type, | |
| const String16& name, | |
| const String16& value, | |
| const Vector<StringPool::entry_style_span>* style = NULL, | |
| const ResTable_config* params = NULL, | |
| const bool doSetIndex = false, | |
| const int32_t format = ResTable_map::TYPE_ANY, | |
| const bool overwrite = false); | |
| status_t startBag(const SourcePos& pos, | |
| const String16& package, | |
| const String16& type, | |
| const String16& name, | |
| const String16& bagParent, | |
| const ResTable_config* params = NULL, | |
| bool overlay = false, | |
| bool replace = false, | |
| bool isId = false); | |
| status_t addBag(const SourcePos& pos, | |
| const String16& package, | |
| const String16& type, | |
| const String16& name, | |
| const String16& bagParent, | |
| const String16& bagKey, | |
| const String16& value, | |
| const Vector<StringPool::entry_style_span>* style = NULL, | |
| const ResTable_config* params = NULL, | |
| bool replace = false, | |
| bool isId = false, | |
| const int32_t format = ResTable_map::TYPE_ANY); | |
| bool hasBagOrEntry(const String16& package, | |
| const String16& type, | |
| const String16& name) const; | |
| bool hasBagOrEntry(const String16& package, | |
| const String16& type, | |
| const String16& name, | |
| const ResTable_config& config) const; | |
| bool hasBagOrEntry(const String16& ref, | |
| const String16* defType = NULL, | |
| const String16* defPackage = NULL); | |
| bool appendComment(const String16& package, | |
| const String16& type, | |
| const String16& name, | |
| const String16& comment, | |
| bool onlyIfEmpty = false); | |
| bool appendTypeComment(const String16& package, | |
| const String16& type, | |
| const String16& name, | |
| const String16& comment); | |
| void canAddEntry(const SourcePos& pos, | |
| const String16& package, const String16& type, const String16& name); | |
| size_t size() const; | |
| size_t numLocalResources() const; | |
| bool hasResources() const; | |
| bool versionForCompat(const Bundle* bundle, const String16& resourceName, | |
| const sp<AaptFile>& file, const sp<XMLNode>& root); | |
| status_t modifyForCompat(const Bundle* bundle); | |
| status_t modifyForCompat(const Bundle* bundle, | |
| const String16& resourceName, | |
| const sp<AaptFile>& file, | |
| const sp<XMLNode>& root); | |
| status_t processBundleFormat(const Bundle* bundle, | |
| const String16& resourceName, | |
| const sp<AaptFile>& file, | |
| const sp<XMLNode>& parent); | |
| sp<AaptFile> flatten(Bundle* bundle, const sp<const ResourceFilter>& filter, | |
| const bool isBase); | |
| static inline uint32_t makeResId(uint32_t packageId, | |
| uint32_t typeId, | |
| uint32_t nameId) | |
| { | |
| return nameId | (typeId<<16) | (packageId<<24); | |
| } | |
| static inline uint32_t getResId(const sp<Package>& p, | |
| const sp<Type>& t, | |
| uint32_t nameId); | |
| uint32_t getResId(const String16& package, | |
| const String16& type, | |
| const String16& name, | |
| bool onlyPublic = true) const; | |
| uint32_t getResId(const String16& ref, | |
| const String16* defType = NULL, | |
| const String16* defPackage = NULL, | |
| const char** outErrorMsg = NULL, | |
| bool onlyPublic = true) const; | |
| static bool isValidResourceName(const String16& s); | |
| bool stringToValue(Res_value* outValue, StringPool* pool, | |
| const String16& str, | |
| bool preserveSpaces, bool coerceType, | |
| uint32_t attrID, | |
| const Vector<StringPool::entry_style_span>* style = NULL, | |
| String16* outStr = NULL, void* accessorCookie = NULL, | |
| uint32_t attrType = ResTable_map::TYPE_ANY, | |
| const String8* configTypeName = NULL, | |
| const ConfigDescription* config = NULL); | |
| status_t assignResourceIds(); | |
| status_t addSymbols(const sp<AaptSymbols>& outSymbols = NULL, | |
| bool skipSymbolsWithoutDefaultLocalization = false); | |
| void addLocalization(const String16& name, const String8& locale, const SourcePos& src); | |
| void addDefaultLocalization(const String16& name); | |
| status_t validateLocalizations(void); | |
| status_t flatten(Bundle* bundle, const sp<const ResourceFilter>& filter, | |
| const sp<AaptFile>& dest, const bool isBase); | |
| status_t flattenLibraryTable(const sp<AaptFile>& dest, const Vector<sp<Package> >& libs); | |
| void writePublicDefinitions(const String16& package, FILE* fp); | |
| virtual uint32_t getCustomResource(const String16& package, | |
| const String16& type, | |
| const String16& name) const; | |
| virtual uint32_t getCustomResourceWithCreation(const String16& package, | |
| const String16& type, | |
| const String16& name, | |
| const bool createIfNeeded); | |
| virtual uint32_t getRemappedPackage(uint32_t origPackage) const; | |
| virtual bool getAttributeType(uint32_t attrID, uint32_t* outType); | |
| virtual bool getAttributeMin(uint32_t attrID, uint32_t* outMin); | |
| virtual bool getAttributeMax(uint32_t attrID, uint32_t* outMax); | |
| virtual bool getAttributeKeys(uint32_t attrID, Vector<String16>* outKeys); | |
| virtual bool getAttributeEnum(uint32_t attrID, | |
| const char16_t* name, size_t nameLen, | |
| Res_value* outValue); | |
| virtual bool getAttributeFlags(uint32_t attrID, | |
| const char16_t* name, size_t nameLen, | |
| Res_value* outValue); | |
| virtual uint32_t getAttributeL10N(uint32_t attrID); | |
| virtual bool getLocalizationSetting(); | |
| virtual void reportError(void* accessorCookie, const char* fmt, ...); | |
| void setCurrentXmlPos(const SourcePos& pos) { mCurrentXmlPos = pos; } | |
| class Item { | |
| public: | |
| Item() : isId(false), format(ResTable_map::TYPE_ANY), bagKeyId(0), evaluating(false) | |
| { memset(&parsedValue, 0, sizeof(parsedValue)); } | |
| Item(const SourcePos& pos, | |
| bool _isId, | |
| const String16& _value, | |
| const Vector<StringPool::entry_style_span>* _style = NULL, | |
| int32_t format = ResTable_map::TYPE_ANY); | |
| Item(const Item& o) : sourcePos(o.sourcePos), | |
| isId(o.isId), value(o.value), style(o.style), | |
| format(o.format), bagKeyId(o.bagKeyId), evaluating(false) { | |
| memset(&parsedValue, 0, sizeof(parsedValue)); | |
| } | |
| ~Item() { } | |
| Item& operator=(const Item& o) { | |
| sourcePos = o.sourcePos; | |
| isId = o.isId; | |
| value = o.value; | |
| style = o.style; | |
| format = o.format; | |
| bagKeyId = o.bagKeyId; | |
| parsedValue = o.parsedValue; | |
| return *this; | |
| } | |
| SourcePos sourcePos; | |
| mutable bool isId; | |
| String16 value; | |
| Vector<StringPool::entry_style_span> style; | |
| int32_t format; | |
| uint32_t bagKeyId; | |
| mutable bool evaluating; | |
| Res_value parsedValue; | |
| }; | |
| class Entry : public RefBase { | |
| public: | |
| Entry(const String16& name, const SourcePos& pos) | |
| : mName(name), mType(TYPE_UNKNOWN), | |
| mItemFormat(ResTable_map::TYPE_ANY), mNameIndex(-1), mPos(pos) | |
| { } | |
| Entry(const Entry& entry); | |
| Entry& operator=(const Entry& entry); | |
| virtual ~Entry() { } | |
| enum type { | |
| TYPE_UNKNOWN = 0, | |
| TYPE_ITEM, | |
| TYPE_BAG | |
| }; | |
| String16 getName() const { return mName; } | |
| type getType() const { return mType; } | |
| void setParent(const String16& parent) { mParent = parent; } | |
| String16 getParent() const { return mParent; } | |
| status_t makeItABag(const SourcePos& sourcePos); | |
| status_t emptyBag(const SourcePos& sourcePos); | |
| status_t setItem(const SourcePos& pos, | |
| const String16& value, | |
| const Vector<StringPool::entry_style_span>* style = NULL, | |
| int32_t format = ResTable_map::TYPE_ANY, | |
| const bool overwrite = false); | |
| status_t addToBag(const SourcePos& pos, | |
| const String16& key, const String16& value, | |
| const Vector<StringPool::entry_style_span>* style = NULL, | |
| bool replace=false, bool isId = false, | |
| int32_t format = ResTable_map::TYPE_ANY); | |
| status_t removeFromBag(const String16& key); | |
| // Index of the entry's name string in the key pool. | |
| int32_t getNameIndex() const { return mNameIndex; } | |
| void setNameIndex(int32_t index) { mNameIndex = index; } | |
| const Item* getItem() const { return mType == TYPE_ITEM ? &mItem : NULL; } | |
| const KeyedVector<String16, Item>& getBag() const { return mBag; } | |
| status_t generateAttributes(ResourceTable* table, | |
| const String16& package); | |
| status_t assignResourceIds(ResourceTable* table, | |
| const String16& package); | |
| status_t prepareFlatten(StringPool* strings, ResourceTable* table, | |
| const String8* configTypeName, const ConfigDescription* config); | |
| status_t remapStringValue(StringPool* strings); | |
| ssize_t flatten(Bundle*, const sp<AaptFile>& data, bool isPublic); | |
| const SourcePos& getPos() const { return mPos; } | |
| private: | |
| String16 mName; | |
| String16 mParent; | |
| type mType; | |
| Item mItem; | |
| int32_t mItemFormat; | |
| KeyedVector<String16, Item> mBag; | |
| int32_t mNameIndex; | |
| uint32_t mParentId; | |
| SourcePos mPos; | |
| }; | |
| class ConfigList : public RefBase { | |
| public: | |
| ConfigList(const String16& name, const SourcePos& pos) | |
| : mName(name), mPos(pos), mPublic(false), mEntryIndex(-1) { } | |
| virtual ~ConfigList() { } | |
| String16 getName() const { return mName; } | |
| const SourcePos& getPos() const { return mPos; } | |
| void appendComment(const String16& comment, bool onlyIfEmpty = false); | |
| const String16& getComment() const { return mComment; } | |
| void appendTypeComment(const String16& comment); | |
| const String16& getTypeComment() const { return mTypeComment; } | |
| // Index of this entry in its Type. | |
| int32_t getEntryIndex() const { return mEntryIndex; } | |
| void setEntryIndex(int32_t index) { mEntryIndex = index; } | |
| void setPublic(bool pub) { mPublic = pub; } | |
| bool getPublic() const { return mPublic; } | |
| void setPublicSourcePos(const SourcePos& pos) { mPublicSourcePos = pos; } | |
| const SourcePos& getPublicSourcePos() { return mPublicSourcePos; } | |
| void addEntry(const ResTable_config& config, const sp<Entry>& entry) { | |
| mEntries.add(config, entry); | |
| } | |
| void removeEntry(const ResTable_config& config) { | |
| mEntries.removeItem(config); | |
| } | |
| const DefaultKeyedVector<ConfigDescription, sp<Entry> >& getEntries() const { return mEntries; } | |
| private: | |
| const String16 mName; | |
| const SourcePos mPos; | |
| String16 mComment; | |
| String16 mTypeComment; | |
| bool mPublic; | |
| SourcePos mPublicSourcePos; | |
| int32_t mEntryIndex; | |
| DefaultKeyedVector<ConfigDescription, sp<Entry> > mEntries; | |
| }; | |
| class Public { | |
| public: | |
| Public() : sourcePos(), ident(0) { } | |
| Public(const SourcePos& pos, | |
| const String16& _comment, | |
| uint32_t _ident) | |
| : sourcePos(pos), | |
| comment(_comment), ident(_ident) { } | |
| Public(const Public& o) : sourcePos(o.sourcePos), | |
| comment(o.comment), ident(o.ident) { } | |
| ~Public() { } | |
| Public& operator=(const Public& o) { | |
| sourcePos = o.sourcePos; | |
| comment = o.comment; | |
| ident = o.ident; | |
| return *this; | |
| } | |
| SourcePos sourcePos; | |
| String16 comment; | |
| uint32_t ident; | |
| }; | |
| class Type : public RefBase { | |
| public: | |
| Type(const String16& name, const SourcePos& pos) | |
| : mName(name), mFirstPublicSourcePos(NULL), mPublicIndex(-1), mIndex(-1), mPos(pos) | |
| { } | |
| virtual ~Type() { delete mFirstPublicSourcePos; } | |
| status_t addPublic(const SourcePos& pos, | |
| const String16& name, | |
| const uint32_t ident); | |
| void canAddEntry(const String16& name); | |
| String16 getName() const { return mName; } | |
| sp<Entry> getEntry(const String16& entry, | |
| const SourcePos& pos, | |
| const ResTable_config* config = NULL, | |
| bool doSetIndex = false, | |
| bool overlay = false, | |
| bool autoAddOverlay = false); | |
| bool isPublic(const String16& entry) const { | |
| return mPublic.indexOfKey(entry) >= 0; | |
| } | |
| sp<ConfigList> removeEntry(const String16& entry); | |
| SortedVector<ConfigDescription> getUniqueConfigs() const; | |
| const SourcePos& getFirstPublicSourcePos() const { return *mFirstPublicSourcePos; } | |
| int32_t getPublicIndex() const { return mPublicIndex; } | |
| int32_t getIndex() const { return mIndex; } | |
| void setIndex(int32_t index) { mIndex = index; } | |
| status_t applyPublicEntryOrder(); | |
| const DefaultKeyedVector<String16, sp<ConfigList> >& getConfigs() const { return mConfigs; } | |
| const Vector<sp<ConfigList> >& getOrderedConfigs() const { return mOrderedConfigs; } | |
| const SortedVector<String16>& getCanAddEntries() const { return mCanAddEntries; } | |
| const SourcePos& getPos() const { return mPos; } | |
| private: | |
| String16 mName; | |
| SourcePos* mFirstPublicSourcePos; | |
| DefaultKeyedVector<String16, Public> mPublic; | |
| DefaultKeyedVector<String16, sp<ConfigList> > mConfigs; | |
| Vector<sp<ConfigList> > mOrderedConfigs; | |
| SortedVector<String16> mCanAddEntries; | |
| int32_t mPublicIndex; | |
| int32_t mIndex; | |
| SourcePos mPos; | |
| }; | |
| class Package : public RefBase { | |
| public: | |
| Package(const String16& name, size_t packageId); | |
| virtual ~Package() { } | |
| String16 getName() const { return mName; } | |
| sp<Type> getType(const String16& type, | |
| const SourcePos& pos, | |
| bool doSetIndex = false); | |
| size_t getAssignedId() const { return mPackageId; } | |
| const ResStringPool& getTypeStrings() const { return mTypeStrings; } | |
| uint32_t indexOfTypeString(const String16& s) const { return mTypeStringsMapping.valueFor(s); } | |
| const sp<AaptFile> getTypeStringsData() const { return mTypeStringsData; } | |
| status_t setTypeStrings(const sp<AaptFile>& data); | |
| const ResStringPool& getKeyStrings() const { return mKeyStrings; } | |
| uint32_t indexOfKeyString(const String16& s) const { return mKeyStringsMapping.valueFor(s); } | |
| const sp<AaptFile> getKeyStringsData() const { return mKeyStringsData; } | |
| status_t setKeyStrings(const sp<AaptFile>& data); | |
| status_t applyPublicTypeOrder(); | |
| const DefaultKeyedVector<String16, sp<Type> >& getTypes() const { return mTypes; } | |
| const Vector<sp<Type> >& getOrderedTypes() const { return mOrderedTypes; } | |
| void movePrivateAttrs(); | |
| private: | |
| status_t setStrings(const sp<AaptFile>& data, | |
| ResStringPool* strings, | |
| DefaultKeyedVector<String16, uint32_t>* mappings); | |
| const String16 mName; | |
| const size_t mPackageId; | |
| DefaultKeyedVector<String16, sp<Type> > mTypes; | |
| Vector<sp<Type> > mOrderedTypes; | |
| sp<AaptFile> mTypeStringsData; | |
| sp<AaptFile> mKeyStringsData; | |
| ResStringPool mTypeStrings; | |
| ResStringPool mKeyStrings; | |
| DefaultKeyedVector<String16, uint32_t> mTypeStringsMapping; | |
| DefaultKeyedVector<String16, uint32_t> mKeyStringsMapping; | |
| }; | |
| void getDensityVaryingResources(KeyedVector<Symbol, Vector<SymbolDefinition> >& resources); | |
| /** | |
| * Make an attribute with the specified format. If another attribute with the same name but | |
| * different format exists, this method returns false. If the name is not taken, or if the | |
| * format is identical, this returns true. | |
| */ | |
| bool makeAttribute(const String16& package, | |
| const String16& name, | |
| const SourcePos& source, | |
| int32_t format, | |
| const String16& comment, | |
| bool appendComment); | |
| sp<Package> getPackage(const String16& package); | |
| private: | |
| void writePublicDefinitions(const String16& package, FILE* fp, bool pub); | |
| sp<Type> getType(const String16& package, | |
| const String16& type, | |
| const SourcePos& pos, | |
| bool doSetIndex = false); | |
| sp<Entry> getEntry(const String16& package, | |
| const String16& type, | |
| const String16& name, | |
| const SourcePos& pos, | |
| bool overlay, | |
| const ResTable_config* config = NULL, | |
| bool doSetIndex = false); | |
| sp<const Entry> getEntry(uint32_t resID, | |
| const ResTable_config* config = NULL) const; | |
| sp<ConfigList> getConfigList(const String16& package, | |
| const String16& type, | |
| const String16& name) const; | |
| const Item* getItem(uint32_t resID, uint32_t attrID) const; | |
| bool getItemValue(uint32_t resID, uint32_t attrID, | |
| Res_value* outValue); | |
| int getPublicAttributeSdkLevel(uint32_t attrId) const; | |
| status_t processBundleFormatImpl(const Bundle* bundle, | |
| const String16& resourceName, | |
| const sp<AaptFile>& file, | |
| const sp<XMLNode>& parent, | |
| Vector<sp<XMLNode> >* namespaces); | |
| String16 mAssetsPackage; | |
| PackageType mPackageType; | |
| sp<AaptAssets> mAssets; | |
| uint32_t mTypeIdOffset; | |
| DefaultKeyedVector<String16, sp<Package> > mPackages; | |
| Vector<sp<Package> > mOrderedPackages; | |
| size_t mNumLocal; | |
| SourcePos mCurrentXmlPos; | |
| Bundle* mBundle; | |
| // key = string resource name, value = set of locales in which that name is defined | |
| std::map<String16, std::map<String8, SourcePos>> mLocalizations; | |
| // set of string resources names that have a default localization | |
| std::set<String16> mHasDefaultLocalization; | |
| std::queue<CompileResourceWorkItem> mWorkQueue; | |
| }; | |
| #endif |