ResourceTable.h revision 5892248580859620db90d5ef2e3c2f48531933fa
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
20class XMLNode;
21class ResourceTable;
22
23enum {
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
36status_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
43status_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
51status_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
59status_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
66struct AccessorCookie
67{
68    SourcePos sourcePos;
69    String8 attr;
70    String8 value;
71
72    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.
82struct CompileResourceWorkItem {
83    String16 resourceName;
84    String8 resPath;
85    sp<AaptFile> file;
86};
87
88class ResourceTable : public ResTable::Accessor
89{
90public:
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
103    ResourceTable(Bundle* bundle, const String16& assetsPackage, PackageType type);
104
105    const String16& getAssetsPackage() const {
106        return mAssetsPackage;
107    }
108
109    /**
110     * Returns the queue of resources that need to be compiled.
111     * This is only used for resources that have been generated
112     * during the compilation phase. If they were just added
113     * to the AaptAssets, then they may be skipped over
114     * and would mess up iteration order for the existing
115     * resources.
116     */
117    std::queue<CompileResourceWorkItem>& getWorkQueue() {
118        return mWorkQueue;
119    }
120
121    status_t addIncludedResources(Bundle* bundle, const sp<AaptAssets>& assets);
122
123    status_t addPublic(const SourcePos& pos,
124                       const String16& package,
125                       const String16& type,
126                       const String16& name,
127                       const uint32_t ident);
128
129    status_t addEntry(const SourcePos& pos,
130                      const String16& package,
131                      const String16& type,
132                      const String16& name,
133                      const String16& value,
134                      const Vector<StringPool::entry_style_span>* style = NULL,
135                      const ResTable_config* params = NULL,
136                      const bool doSetIndex = false,
137                      const int32_t format = ResTable_map::TYPE_ANY,
138                      const bool overwrite = false);
139
140    status_t startBag(const SourcePos& pos,
141                    const String16& package,
142                    const String16& type,
143                    const String16& name,
144                    const String16& bagParent,
145                    const ResTable_config* params = NULL,
146                    bool overlay = false,
147                    bool replace = false,
148                    bool isId = false);
149
150    status_t addBag(const SourcePos& pos,
151                    const String16& package,
152                    const String16& type,
153                    const String16& name,
154                    const String16& bagParent,
155                    const String16& bagKey,
156                    const String16& value,
157                    const Vector<StringPool::entry_style_span>* style = NULL,
158                    const ResTable_config* params = NULL,
159                    bool replace = false,
160                    bool isId = false,
161                    const int32_t format = ResTable_map::TYPE_ANY);
162
163    bool hasBagOrEntry(const String16& package,
164                       const String16& type,
165                       const String16& name) const;
166
167    bool hasBagOrEntry(const String16& package,
168                       const String16& type,
169                       const String16& name,
170                       const ResTable_config& config) const;
171
172    bool hasBagOrEntry(const String16& ref,
173                       const String16* defType = NULL,
174                       const String16* defPackage = NULL);
175
176    bool appendComment(const String16& package,
177                       const String16& type,
178                       const String16& name,
179                       const String16& comment,
180                       bool onlyIfEmpty = false);
181
182    bool appendTypeComment(const String16& package,
183                           const String16& type,
184                           const String16& name,
185                           const String16& comment);
186
187    void canAddEntry(const SourcePos& pos,
188        const String16& package, const String16& type, const String16& name);
189
190    size_t size() const;
191    size_t numLocalResources() const;
192    bool hasResources() const;
193
194    status_t modifyForCompat(const Bundle* bundle);
195    status_t modifyForCompat(const Bundle* bundle,
196                             const String16& resourceName,
197                             const sp<AaptFile>& file,
198                             const sp<XMLNode>& root);
199
200    sp<AaptFile> flatten(Bundle* bundle, const sp<const ResourceFilter>& filter,
201            const bool isBase);
202
203    static inline uint32_t makeResId(uint32_t packageId,
204                                     uint32_t typeId,
205                                     uint32_t nameId)
206    {
207        return nameId | (typeId<<16) | (packageId<<24);
208    }
209
210    static inline uint32_t getResId(const sp<Package>& p,
211                                    const sp<Type>& t,
212                                    uint32_t nameId);
213
214    uint32_t getResId(const String16& package,
215                      const String16& type,
216                      const String16& name,
217                      bool onlyPublic = true) const;
218
219    uint32_t getResId(const String16& ref,
220                      const String16* defType = NULL,
221                      const String16* defPackage = NULL,
222                      const char** outErrorMsg = NULL,
223                      bool onlyPublic = true) const;
224
225    static bool isValidResourceName(const String16& s);
226
227    bool stringToValue(Res_value* outValue, StringPool* pool,
228                       const String16& str,
229                       bool preserveSpaces, bool coerceType,
230                       uint32_t attrID,
231                       const Vector<StringPool::entry_style_span>* style = NULL,
232                       String16* outStr = NULL, void* accessorCookie = NULL,
233                       uint32_t attrType = ResTable_map::TYPE_ANY,
234                       const String8* configTypeName = NULL,
235                       const ConfigDescription* config = NULL);
236
237    status_t assignResourceIds();
238    status_t addSymbols(const sp<AaptSymbols>& outSymbols = NULL,
239                        bool skipSymbolsWithoutDefaultLocalization = false);
240    void addLocalization(const String16& name, const String8& locale, const SourcePos& src);
241    void addDefaultLocalization(const String16& name);
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
273    void setCurrentXmlPos(const SourcePos& pos) { mCurrentXmlPos = pos; }
274
275    class Item {
276    public:
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);
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        }
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:
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
322        virtual ~Entry() { }
323
324        enum type {
325            TYPE_UNKNOWN = 0,
326            TYPE_ITEM,
327            TYPE_BAG
328        };
329
330        String16 getName() const { return mName; }
331        type getType() const { return mType; }
332
333        void setParent(const String16& parent) { mParent = parent; }
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.
355        int32_t getNameIndex() const { return mNameIndex; }
356        void setNameIndex(int32_t index) { mNameIndex = index; }
357
358        const Item* getItem() const { return mType == TYPE_ITEM ? &mItem : NULL; }
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
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:
390        ConfigList(const String16& name, const SourcePos& pos)
391            : mName(name), mPos(pos), mPublic(false), mEntryIndex(-1) { }
392        virtual ~ConfigList() { }
393
394        String16 getName() const { return mName; }
395        const SourcePos& getPos() const { return mPos; }
396
397        void appendComment(const String16& comment, bool onlyIfEmpty = false);
398        const String16& getComment() const { return mComment; }
399
400        void appendTypeComment(const String16& comment);
401        const String16& getTypeComment() const { return mTypeComment; }
402
403        // Index of this entry in its Type.
404        int32_t getEntryIndex() const { return mEntryIndex; }
405        void setEntryIndex(int32_t index) { mEntryIndex = index; }
406
407        void setPublic(bool pub) { mPublic = pub; }
408        bool getPublic() const { return mPublic; }
409        void setPublicSourcePos(const SourcePos& pos) { mPublicSourcePos = pos; }
410        const SourcePos& getPublicSourcePos() { return mPublicSourcePos; }
411
412        void addEntry(const ResTable_config& config, const sp<Entry>& entry) {
413            mEntries.add(config, entry);
414        }
415
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:
430        Public() : sourcePos(), ident(0) { }
431        Public(const SourcePos& pos,
432               const String16& _comment,
433               uint32_t _ident)
434            : sourcePos(pos),
435            comment(_comment), ident(_ident) { }
436        Public(const Public& o) : sourcePos(o.sourcePos),
437            comment(o.comment), ident(o.ident) { }
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:
454        Type(const String16& name, const SourcePos& pos)
455                : mName(name), mFirstPublicSourcePos(NULL), mPublicIndex(-1), mIndex(-1), mPos(pos)
456        { }
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
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
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
481        const SourcePos& getFirstPublicSourcePos() const { return *mFirstPublicSourcePos; }
482
483        int32_t getPublicIndex() const { return mPublicIndex; }
484
485        int32_t getIndex() const { return mIndex; }
486        void setIndex(int32_t index) { mIndex = index; }
487
488        status_t applyPublicEntryOrder();
489
490        const DefaultKeyedVector<String16, sp<ConfigList> >& getConfigs() const { return mConfigs; }
491        const Vector<sp<ConfigList> >& getOrderedConfigs() const { return mOrderedConfigs; }
492        const SortedVector<String16>& getCanAddEntries() const { return mCanAddEntries; }
493
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);
511        virtual ~Package() { }
512
513        String16 getName() const { return mName; }
514        sp<Type> getType(const String16& type,
515                         const SourcePos& pos,
516                         bool doSetIndex = false);
517
518        size_t getAssignedId() const { return mPackageId; }
519
520        const ResStringPool& getTypeStrings() const { return mTypeStrings; }
521        uint32_t indexOfTypeString(const String16& s) const { return mTypeStringsMapping.valueFor(s); }
522        const sp<AaptFile> getTypeStringsData() const { return mTypeStringsData; }
523        status_t setTypeStrings(const sp<AaptFile>& data);
524
525        const ResStringPool& getKeyStrings() const { return mKeyStrings; }
526        uint32_t indexOfKeyString(const String16& s) const { return mKeyStringsMapping.valueFor(s); }
527        const sp<AaptFile> getKeyStringsData() const { return mKeyStringsData; }
528        status_t setKeyStrings(const sp<AaptFile>& data);
529
530        status_t applyPublicTypeOrder();
531
532        const DefaultKeyedVector<String16, sp<Type> >& getTypes() const { return mTypes; }
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
556private:
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    std::map<String16, std::map<String8, SourcePos>> mLocalizations;
593    // set of string resources names that have a default localization
594    std::set<String16> mHasDefaultLocalization;
595    std::queue<CompileResourceWorkItem> mWorkQueue;
596};
597
598#endif
599