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