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
20using namespace std;
21
22class XMLNode;
23class ResourceTable;
24
25enum {
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
38status_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
45status_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
53status_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
61status_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
68struct AccessorCookie
69{
70    SourcePos sourcePos;
71    String8 attr;
72    String8 value;
73
74    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.
84struct CompileResourceWorkItem {
85    String16 resourceName;
86    String8 resPath;
87    sp<AaptFile> file;
88};
89
90class ResourceTable : public ResTable::Accessor
91{
92public:
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
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     */
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
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
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    map<String16, map<String8, SourcePos> > mLocalizations;
593    queue<CompileResourceWorkItem> mWorkQueue;
594};
595
596#endif
597