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