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