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