1282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//
2282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// Copyright 2006 The Android Open Source Project
3282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//
4282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// Build resource files from raw assets.
5282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//
6282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
7282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "ResourceTable.h"
8282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
9282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "XMLNode.h"
10282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "ResourceFilter.h"
11282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "ResourceIdCache.h"
12282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
13282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <androidfw/ResourceTypes.h>
14282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <utils/ByteOrder.h>
1582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski#include <utils/TypeHelpers.h>
16282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <stdarg.h>
17282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
18282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#define NOISY(x) //x
19282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
20e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinskistatus_t compileXmlFile(const Bundle* bundle,
21e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                        const sp<AaptAssets>& assets,
22e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                        const String16& resourceName,
23282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const sp<AaptFile>& target,
24282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ResourceTable* table,
25282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        int options)
26282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
27282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<XMLNode> root = XMLNode::parse(target);
28282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (root == NULL) {
29282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
30282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
31a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin
32e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    return compileXmlFile(bundle, assets, resourceName, root, target, table, options);
33282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
34282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
35e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinskistatus_t compileXmlFile(const Bundle* bundle,
36e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                        const sp<AaptAssets>& assets,
37e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                        const String16& resourceName,
38282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const sp<AaptFile>& target,
39282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const sp<AaptFile>& outTarget,
40282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ResourceTable* table,
41282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        int options)
42282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
43282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<XMLNode> root = XMLNode::parse(target);
44282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (root == NULL) {
45282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
46282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
47282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
48e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    return compileXmlFile(bundle, assets, resourceName, root, outTarget, table, options);
49282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
50282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
51e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinskistatus_t compileXmlFile(const Bundle* bundle,
52e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                        const sp<AaptAssets>& assets,
53e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                        const String16& resourceName,
54282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const sp<XMLNode>& root,
55282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const sp<AaptFile>& target,
56282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ResourceTable* table,
57282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        int options)
58282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
59282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if ((options&XML_COMPILE_STRIP_WHITESPACE) != 0) {
60282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        root->removeWhitespace(true, NULL);
61282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else  if ((options&XML_COMPILE_COMPACT_WHITESPACE) != 0) {
62282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        root->removeWhitespace(false, NULL);
63282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
64282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
65282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if ((options&XML_COMPILE_UTF8) != 0) {
66282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        root->setUTF8(true);
67282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
68282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
69282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool hasErrors = false;
70282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
71282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if ((options&XML_COMPILE_ASSIGN_ATTRIBUTE_IDS) != 0) {
72282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        status_t err = root->assignResourceIds(assets, table);
73282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != NO_ERROR) {
74282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            hasErrors = true;
75282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
76282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
77282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
78282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = root->parseValues(assets, table);
79282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
80282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        hasErrors = true;
81282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
82282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
83282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (hasErrors) {
84282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
85282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
86e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski
87e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    if (table->modifyForCompat(bundle, resourceName, target, root) != NO_ERROR) {
88e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        return UNKNOWN_ERROR;
89e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    }
90282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
91282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    NOISY(printf("Input XML Resource:\n"));
92282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    NOISY(root->print());
93282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    err = root->flatten(target,
94282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            (options&XML_COMPILE_STRIP_COMMENTS) != 0,
95282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            (options&XML_COMPILE_STRIP_RAW_VALUES) != 0);
96282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
97282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return err;
98282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
99282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    NOISY(printf("Output XML Resource:\n"));
101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    NOISY(ResXMLTree tree;
102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        tree.setTo(target->getData(), target->getSize());
103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printXMLBlock(&tree));
104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    target->setCompressionMethod(ZipEntry::kCompressDeflated);
106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return err;
108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#undef NOISY
111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#define NOISY(x) //x
112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistruct flag_entry
114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char16_t* name;
116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t nameLen;
117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t value;
118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char* description;
119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski};
120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t referenceArray[] =
122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { 'r', 'e', 'f', 'e', 'r', 'e', 'n', 'c', 'e' };
123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t stringArray[] =
124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { 's', 't', 'r', 'i', 'n', 'g' };
125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t integerArray[] =
126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { 'i', 'n', 't', 'e', 'g', 'e', 'r' };
127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t booleanArray[] =
128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { 'b', 'o', 'o', 'l', 'e', 'a', 'n' };
129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t colorArray[] =
130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { 'c', 'o', 'l', 'o', 'r' };
131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t floatArray[] =
132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { 'f', 'l', 'o', 'a', 't' };
133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t dimensionArray[] =
134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { 'd', 'i', 'm', 'e', 'n', 's', 'i', 'o', 'n' };
135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t fractionArray[] =
136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { 'f', 'r', 'a', 'c', 't', 'i', 'o', 'n' };
137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t enumArray[] =
138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { 'e', 'n', 'u', 'm' };
139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t flagsArray[] =
140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { 'f', 'l', 'a', 'g', 's' };
141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const flag_entry gFormatFlags[] = {
143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { referenceArray, sizeof(referenceArray)/2, ResTable_map::TYPE_REFERENCE,
144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      "a reference to another resource, in the form \"<code>@[+][<i>package</i>:]<i>type</i>:<i>name</i></code>\"\n"
145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      "or to a theme attribute in the form \"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>\"."},
146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { stringArray, sizeof(stringArray)/2, ResTable_map::TYPE_STRING,
147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      "a string value, using '\\\\;' to escape characters such as '\\\\n' or '\\\\uxxxx' for a unicode character." },
148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { integerArray, sizeof(integerArray)/2, ResTable_map::TYPE_INTEGER,
149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      "an integer value, such as \"<code>100</code>\"." },
150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { booleanArray, sizeof(booleanArray)/2, ResTable_map::TYPE_BOOLEAN,
151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      "a boolean value, either \"<code>true</code>\" or \"<code>false</code>\"." },
152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { colorArray, sizeof(colorArray)/2, ResTable_map::TYPE_COLOR,
153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      "a color value, in the form of \"<code>#<i>rgb</i></code>\", \"<code>#<i>argb</i></code>\",\n"
154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      "\"<code>#<i>rrggbb</i></code>\", or \"<code>#<i>aarrggbb</i></code>\"." },
155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { floatArray, sizeof(floatArray)/2, ResTable_map::TYPE_FLOAT,
156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      "a floating point value, such as \"<code>1.2</code>\"."},
157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { dimensionArray, sizeof(dimensionArray)/2, ResTable_map::TYPE_DIMENSION,
158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      "a dimension value, which is a floating point number appended with a unit such as \"<code>14.5sp</code>\".\n"
159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      "Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),\n"
160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      "in (inches), mm (millimeters)." },
161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { fractionArray, sizeof(fractionArray)/2, ResTable_map::TYPE_FRACTION,
162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      "a fractional value, which is a floating point number appended with either % or %p, such as \"<code>14.5%</code>\".\n"
163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      "The % suffix always means a percentage of the base size; the optional %p suffix provides a size relative to\n"
164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      "some parent container." },
165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { enumArray, sizeof(enumArray)/2, ResTable_map::TYPE_ENUM, NULL },
166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { flagsArray, sizeof(flagsArray)/2, ResTable_map::TYPE_FLAGS, NULL },
167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { NULL, 0, 0, NULL }
168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski};
169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t suggestedArray[] = { 's', 'u', 'g', 'g', 'e', 's', 't', 'e', 'd' };
171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const flag_entry l10nRequiredFlags[] = {
173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { suggestedArray, sizeof(suggestedArray)/2, ResTable_map::L10N_SUGGESTED, NULL },
174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { NULL, 0, 0, NULL }
175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski};
176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t nulStr[] = { 0 };
178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic uint32_t parse_flags(const char16_t* str, size_t len,
180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                             const flag_entry* flags, bool* outError = NULL)
181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (len > 0 && isspace(*str)) {
183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        str++;
184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        len--;
185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (len > 0 && isspace(str[len-1])) {
187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        len--;
188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char16_t* const end = str + len;
191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t value = 0;
192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (str < end) {
194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const char16_t* div = str;
195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        while (div < end && *div != '|') {
196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            div++;
197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const flag_entry* cur = flags;
200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        while (cur->name) {
201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (strzcmp16(cur->name, cur->nameLen, str, div-str) == 0) {
202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                value |= cur->value;
203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                break;
204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            cur++;
206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!cur->name) {
209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (outError) *outError = true;
210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return 0;
211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        str = div < end ? div+1 : div;
214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (outError) *outError = false;
217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return value;
218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic String16 mayOrMust(int type, int flags)
221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if ((type&(~flags)) == 0) {
223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return String16("<p>Must");
224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return String16("<p>May");
227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic void appendTypeInfo(ResourceTable* outTable, const String16& pkg,
230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String16& typeName, const String16& ident, int type,
231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const flag_entry* flags)
232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool hadType = false;
234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (flags->name) {
235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if ((type&flags->value) != 0 && flags->description != NULL) {
236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String16 fullMsg(mayOrMust(type, flags->value));
237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fullMsg.append(String16(" be "));
238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fullMsg.append(String16(flags->description));
239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            outTable->appendTypeComment(pkg, typeName, ident, fullMsg);
240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            hadType = true;
241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        flags++;
243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (hadType && (type&ResTable_map::TYPE_REFERENCE) == 0) {
245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        outTable->appendTypeComment(pkg, typeName, ident,
246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16("<p>This may also be a reference to a resource (in the form\n"
247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                         "\"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>\") or\n"
248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                         "theme attribute (in the form\n"
249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                         "\"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>\")\n"
250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                         "containing a value of this type."));
251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistruct PendingAttribute
255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 myPackage;
257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const SourcePos sourcePos;
258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const bool appendComment;
259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int32_t type;
260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String16 ident;
261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String16 comment;
262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool hasErrors;
263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool added;
264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    PendingAttribute(String16 _package, const sp<AaptFile>& in,
266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ResXMLTree& block, bool _appendComment)
267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        : myPackage(_package)
268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        , sourcePos(in->getPrintableSource(), block.getLineNumber())
269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        , appendComment(_appendComment)
270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        , type(ResTable_map::TYPE_ANY)
271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        , hasErrors(false)
272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        , added(false)
273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    {
274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t createIfNeeded(ResourceTable* outTable)
277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    {
278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (added || hasErrors) {
279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return NO_ERROR;
280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        added = true;
282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String16 attr16("attr");
284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (outTable->hasBagOrEntry(myPackage, attr16, ident)) {
286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sourcePos.error("Attribute \"%s\" has already been defined\n",
287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(ident).string());
288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            hasErrors = true;
289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return UNKNOWN_ERROR;
290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        char numberStr[16];
293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sprintf(numberStr, "%d", type);
294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        status_t err = outTable->addBag(sourcePos, myPackage,
295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                attr16, ident, String16(""),
296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16("^type"),
297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16(numberStr), NULL, NULL);
298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != NO_ERROR) {
299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            hasErrors = true;
300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return err;
301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        outTable->appendComment(myPackage, attr16, ident, comment, appendComment);
303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //printf("Attribute %s comment: %s\n", String8(ident).string(),
304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //     String8(comment).string());
305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return err;
306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski};
308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic status_t compileAttribute(const sp<AaptFile>& in,
310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 ResXMLTree& block,
311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16& myPackage,
312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 ResourceTable* outTable,
313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 String16* outIdent = NULL,
314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 bool inStyleable = false)
315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    PendingAttribute attr(myPackage, in, block, inStyleable);
317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 attr16("attr");
319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 id16("id");
320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Attribute type constants.
322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 enum16("enum");
323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 flag16("flag");
324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ResXMLTree::event_code_t code;
326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t len;
327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err;
328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t identIdx = block.indexOfAttribute(NULL, "name");
330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (identIdx >= 0) {
331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        attr.ident = String16(block.getAttributeStringValue(identIdx, &len));
332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (outIdent) {
333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            *outIdent = attr.ident;
334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        attr.sourcePos.error("A 'name' attribute is required for <attr>\n");
337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        attr.hasErrors = true;
338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    attr.comment = String16(
341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            block.getComment(&len) ? block.getComment(&len) : nulStr);
342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t typeIdx = block.indexOfAttribute(NULL, "format");
344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (typeIdx >= 0) {
345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String16 typeStr = String16(block.getAttributeStringValue(typeIdx, &len));
346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        attr.type = parse_flags(typeStr.string(), typeStr.size(), gFormatFlags);
347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (attr.type == 0) {
348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            attr.sourcePos.error("Tag <attr> 'format' attribute value \"%s\" not valid\n",
349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(typeStr).string());
350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            attr.hasErrors = true;
351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        attr.createIfNeeded(outTable);
353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else if (!inStyleable) {
354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Attribute definitions outside of styleables always define the
355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // attribute as a generic value.
356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        attr.createIfNeeded(outTable);
357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //printf("Attribute %s: type=0x%08x\n", String8(attr.ident).string(), attr.type);
360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t minIdx = block.indexOfAttribute(NULL, "min");
362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (minIdx >= 0) {
363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String16 val = String16(block.getAttributeStringValue(minIdx, &len));
364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!ResTable::stringToInt(val.string(), val.size(), NULL)) {
365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            attr.sourcePos.error("Tag <attr> 'min' attribute must be a number, not \"%s\"\n",
366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(val).string());
367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            attr.hasErrors = true;
368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        attr.createIfNeeded(outTable);
370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!attr.hasErrors) {
371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            err = outTable->addBag(attr.sourcePos, myPackage, attr16, attr.ident,
372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String16(""), String16("^min"), String16(val), NULL, NULL);
373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (err != NO_ERROR) {
374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                attr.hasErrors = true;
375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t maxIdx = block.indexOfAttribute(NULL, "max");
380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (maxIdx >= 0) {
381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String16 val = String16(block.getAttributeStringValue(maxIdx, &len));
382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!ResTable::stringToInt(val.string(), val.size(), NULL)) {
383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            attr.sourcePos.error("Tag <attr> 'max' attribute must be a number, not \"%s\"\n",
384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(val).string());
385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            attr.hasErrors = true;
386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        attr.createIfNeeded(outTable);
388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!attr.hasErrors) {
389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            err = outTable->addBag(attr.sourcePos, myPackage, attr16, attr.ident,
390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String16(""), String16("^max"), String16(val), NULL, NULL);
391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            attr.hasErrors = true;
392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if ((minIdx >= 0 || maxIdx >= 0) && (attr.type&ResTable_map::TYPE_INTEGER) == 0) {
396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        attr.sourcePos.error("Tag <attr> must have format=integer attribute if using max or min\n");
397282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        attr.hasErrors = true;
398282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t l10nIdx = block.indexOfAttribute(NULL, "localization");
401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (l10nIdx >= 0) {
402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const uint16_t* str = block.getAttributeStringValue(l10nIdx, &len);
403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        bool error;
404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        uint32_t l10n_required = parse_flags(str, len, l10nRequiredFlags, &error);
405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (error) {
406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            attr.sourcePos.error("Tag <attr> 'localization' attribute value \"%s\" not valid\n",
407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(str).string());
408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            attr.hasErrors = true;
409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        attr.createIfNeeded(outTable);
411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!attr.hasErrors) {
412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            char buf[11];
413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sprintf(buf, "%d", l10n_required);
414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            err = outTable->addBag(attr.sourcePos, myPackage, attr16, attr.ident,
415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String16(""), String16("^l10n"), String16(buf), NULL, NULL);
416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (err != NO_ERROR) {
417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                attr.hasErrors = true;
418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String16 enumOrFlagsComment;
423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (code == ResXMLTree::START_TAG) {
426282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            uint32_t localType = 0;
427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (strcmp16(block.getElementName(&len), enum16.string()) == 0) {
428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                localType = ResTable_map::TYPE_ENUM;
429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), flag16.string()) == 0) {
430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                localType = ResTable_map::TYPE_FLAGS;
431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos(in->getPrintableSource(), block.getLineNumber())
433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        .error("Tag <%s> can not appear inside <attr>, only <enum> or <flag>\n",
434282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8(block.getElementName(&len)).string());
435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return UNKNOWN_ERROR;
436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
437282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            attr.createIfNeeded(outTable);
439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
440282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (attr.type == ResTable_map::TYPE_ANY) {
441282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // No type was explicitly stated, so supplying enum tags
442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // implicitly creates an enum or flag.
443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                attr.type = 0;
444282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
445282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if ((attr.type&(ResTable_map::TYPE_ENUM|ResTable_map::TYPE_FLAGS)) == 0) {
447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Wasn't originally specified as an enum, so update its type.
448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                attr.type |= localType;
449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!attr.hasErrors) {
450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    char numberStr[16];
451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sprintf(numberStr, "%d", attr.type);
452282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    err = outTable->addBag(SourcePos(in->getPrintableSource(), block.getLineNumber()),
453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            myPackage, attr16, attr.ident, String16(""),
454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            String16("^type"), String16(numberStr), NULL, NULL, true);
455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (err != NO_ERROR) {
456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        attr.hasErrors = true;
457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if ((uint32_t)(attr.type&(ResTable_map::TYPE_ENUM|ResTable_map::TYPE_FLAGS)) != localType) {
460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (localType == ResTable_map::TYPE_ENUM) {
461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    SourcePos(in->getPrintableSource(), block.getLineNumber())
462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            .error("<enum> attribute can not be used inside a flags format\n");
463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    attr.hasErrors = true;
464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    SourcePos(in->getPrintableSource(), block.getLineNumber())
466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            .error("<flag> attribute can not be used inside a enum format\n");
467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    attr.hasErrors = true;
468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String16 itemIdent;
472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ssize_t itemIdentIdx = block.indexOfAttribute(NULL, "name");
473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (itemIdentIdx >= 0) {
474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                itemIdent = String16(block.getAttributeStringValue(itemIdentIdx, &len));
475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos(in->getPrintableSource(), block.getLineNumber())
477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        .error("A 'name' attribute is required for <enum> or <flag>\n");
478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                attr.hasErrors = true;
479282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String16 value;
482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ssize_t valueIdx = block.indexOfAttribute(NULL, "value");
483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (valueIdx >= 0) {
484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                value = String16(block.getAttributeStringValue(valueIdx, &len));
485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos(in->getPrintableSource(), block.getLineNumber())
487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        .error("A 'value' attribute is required for <enum> or <flag>\n");
488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                attr.hasErrors = true;
489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!attr.hasErrors && !ResTable::stringToInt(value.string(), value.size(), NULL)) {
491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos(in->getPrintableSource(), block.getLineNumber())
492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        .error("Tag <enum> or <flag> 'value' attribute must be a number,"
493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        " not \"%s\"\n",
494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8(value).string());
495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                attr.hasErrors = true;
496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!attr.hasErrors) {
499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (enumOrFlagsComment.size() == 0) {
500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    enumOrFlagsComment.append(mayOrMust(attr.type,
501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            ResTable_map::TYPE_ENUM|ResTable_map::TYPE_FLAGS));
502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    enumOrFlagsComment.append((attr.type&ResTable_map::TYPE_ENUM)
503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       ? String16(" be one of the following constant values.")
504282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       : String16(" be one or more (separated by '|') of the following constant values."));
505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    enumOrFlagsComment.append(String16("</p>\n<table>\n"
506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                "<colgroup align=\"left\" />\n"
507282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                "<colgroup align=\"left\" />\n"
508282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                "<colgroup align=\"left\" />\n"
509282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                "<tr><th>Constant</th><th>Value</th><th>Description</th></tr>"));
510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
511282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
512282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                enumOrFlagsComment.append(String16("\n<tr><td><code>"));
513282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                enumOrFlagsComment.append(itemIdent);
514282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                enumOrFlagsComment.append(String16("</code></td><td>"));
515282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                enumOrFlagsComment.append(value);
516282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                enumOrFlagsComment.append(String16("</td><td>"));
517282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (block.getComment(&len)) {
518282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    enumOrFlagsComment.append(String16(block.getComment(&len)));
519282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
520282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                enumOrFlagsComment.append(String16("</td></tr>"));
521282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
522282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                err = outTable->addBag(SourcePos(in->getPrintableSource(), block.getLineNumber()),
523282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       myPackage,
524282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       attr16, attr.ident, String16(""),
525282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       itemIdent, value, NULL, NULL, false, true);
526282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (err != NO_ERROR) {
527282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    attr.hasErrors = true;
528282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
529282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
530282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else if (code == ResXMLTree::END_TAG) {
531282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (strcmp16(block.getElementName(&len), attr16.string()) == 0) {
532282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                break;
533282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
534282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if ((attr.type&ResTable_map::TYPE_ENUM) != 0) {
535282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (strcmp16(block.getElementName(&len), enum16.string()) != 0) {
536282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    SourcePos(in->getPrintableSource(), block.getLineNumber())
537282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            .error("Found tag </%s> where </enum> is expected\n",
538282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            String8(block.getElementName(&len)).string());
539282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return UNKNOWN_ERROR;
540282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
541282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
542282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (strcmp16(block.getElementName(&len), flag16.string()) != 0) {
543282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    SourcePos(in->getPrintableSource(), block.getLineNumber())
544282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            .error("Found tag </%s> where </flag> is expected\n",
545282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            String8(block.getElementName(&len)).string());
546282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return UNKNOWN_ERROR;
547282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
548282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
549282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
550282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
551282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
552282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (!attr.hasErrors && attr.added) {
553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        appendTypeInfo(outTable, myPackage, attr16, attr.ident, attr.type, gFormatFlags);
554282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
555282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
556282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (!attr.hasErrors && enumOrFlagsComment.size() > 0) {
557282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        enumOrFlagsComment.append(String16("\n</table>"));
558282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        outTable->appendTypeComment(myPackage, attr16, attr.ident, enumOrFlagsComment);
559282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
560282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
561282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
562282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
563282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
564282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
565282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool localeIsDefined(const ResTable_config& config)
566282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
567282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return config.locale == 0;
568282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
569282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
570282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t parseAndAddBag(Bundle* bundle,
571282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const sp<AaptFile>& in,
572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ResXMLTree* block,
573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const ResTable_config& config,
574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const String16& myPackage,
575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const String16& curType,
576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const String16& ident,
577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const String16& parentIdent,
578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const String16& itemIdent,
579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        int32_t curFormat,
580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        bool isFormatted,
581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const String16& product,
582a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                        PseudolocalizationMethod pseudolocalize,
583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const bool overwrite,
584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ResourceTable* outTable)
585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err;
587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 item16("item");
588a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin
589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String16 str;
590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Vector<StringPool::entry_style_span> spans;
591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    err = parseStyledString(bundle, in->getPrintableSource().string(),
592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            block, item16, &str, &spans, isFormatted,
593282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            pseudolocalize);
594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return err;
596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    NOISY(printf("Adding resource bag entry l=%c%c c=%c%c orien=%d d=%d "
599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 " pid=%s, bag=%s, id=%s: %s\n",
600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 config.language[0], config.language[1],
601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 config.country[0], config.country[1],
602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 config.orientation, config.density,
603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 String8(parentIdent).string(),
604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 String8(ident).string(),
605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 String8(itemIdent).string(),
606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 String8(str).string()));
607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    err = outTable->addBag(SourcePos(in->getPrintableSource(), block->getLineNumber()),
609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           myPackage, curType, ident, parentIdent, itemIdent, str,
610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           &spans, &config, overwrite, false, curFormat);
611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return err;
612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Returns true if needle is one of the elements in the comma-separated list
616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * haystack, false otherwise.
617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool isInProductList(const String16& needle, const String16& haystack) {
619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char16_t *needle2 = needle.string();
620282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char16_t *haystack2 = haystack.string();
621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t needlesize = needle.size();
622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (*haystack2 != '\0') {
624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (strncmp16(haystack2, needle2, needlesize) == 0) {
625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (haystack2[needlesize] == '\0' || haystack2[needlesize] == ',') {
626282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return true;
627282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
628282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
629282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
630282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        while (*haystack2 != '\0' && *haystack2 != ',') {
631282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            haystack2++;
632282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
633282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (*haystack2 == ',') {
634282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            haystack2++;
635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
637282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
6418ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski/*
6428ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski * A simple container that holds a resource type and name. It is ordered first by type then
6438ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski * by name.
6448ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski */
6458ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinskistruct type_ident_pair_t {
6468ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    String16 type;
6478ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    String16 ident;
6488ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski
6498ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    type_ident_pair_t() { };
6508ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    type_ident_pair_t(const String16& t, const String16& i) : type(t), ident(i) { }
6518ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    type_ident_pair_t(const type_ident_pair_t& o) : type(o.type), ident(o.ident) { }
6528ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    inline bool operator < (const type_ident_pair_t& o) const {
6538ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski        int cmp = compare_type(type, o.type);
6548ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski        if (cmp < 0) {
6558ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski            return true;
6568ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski        } else if (cmp > 0) {
6578ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski            return false;
6588ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski        } else {
6598ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski            return strictly_order_type(ident, o.ident);
6608ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski        }
6618ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    }
6628ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski};
6638ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski
6648ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski
665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t parseAndAddEntry(Bundle* bundle,
666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const sp<AaptFile>& in,
667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ResXMLTree* block,
668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const ResTable_config& config,
669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const String16& myPackage,
670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const String16& curType,
671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const String16& ident,
672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const String16& curTag,
673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        bool curIsStyled,
674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        int32_t curFormat,
675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        bool isFormatted,
676282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const String16& product,
677a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                        PseudolocalizationMethod pseudolocalize,
678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const bool overwrite,
6798ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                        KeyedVector<type_ident_pair_t, bool>* skippedResourceNames,
680282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ResourceTable* outTable)
681282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
682282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err;
683282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
684282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String16 str;
685282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Vector<StringPool::entry_style_span> spans;
686282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    err = parseStyledString(bundle, in->getPrintableSource().string(), block,
687282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            curTag, &str, curIsStyled ? &spans : NULL,
688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            isFormatted, pseudolocalize);
689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
690282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err < NO_ERROR) {
691282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return err;
692282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
693282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
694282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*
695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * If a product type was specified on the command line
696282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * and also in the string, and the two are not the same,
697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * return without adding the string.
698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
700282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char *bundleProduct = bundle->getProduct();
701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundleProduct == NULL) {
702282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        bundleProduct = "";
703282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
704282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
705282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (product.size() != 0) {
706282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        /*
707282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         * If the command-line-specified product is empty, only "default"
708282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         * matches.  Other variants are skipped.  This is so generation
709282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         * of the R.java file when the product is not known is predictable.
710282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         */
711282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (bundleProduct[0] == '\0') {
713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (strcmp16(String16("default").string(), product.string()) != 0) {
7148ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                /*
7158ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                 * This string has a product other than 'default'. Do not add it,
7168ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                 * but record it so that if we do not see the same string with
7178ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                 * product 'default' or no product, then report an error.
7188ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                 */
7198ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                skippedResourceNames->replaceValueFor(
7208ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                        type_ident_pair_t(curType, ident), true);
721282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return NO_ERROR;
722282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
723282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
724282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            /*
725282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             * The command-line product is not empty.
726282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             * If the product for this string is on the command-line list,
727282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             * it matches.  "default" also matches, but only if nothing
728282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             * else has matched already.
729282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             */
730282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
731282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (isInProductList(product, String16(bundleProduct))) {
732282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ;
733282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(String16("default").string(), product.string()) == 0 &&
734282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       !outTable->hasBagOrEntry(myPackage, curType, ident, config)) {
735282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ;
736282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
737282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return NO_ERROR;
738282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
739282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
740282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
741282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
742282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    NOISY(printf("Adding resource entry l=%c%c c=%c%c orien=%d d=%d id=%s: %s\n",
743282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 config.language[0], config.language[1],
744282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 config.country[0], config.country[1],
745282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 config.orientation, config.density,
746282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 String8(ident).string(), String8(str).string()));
747282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
748282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    err = outTable->addEntry(SourcePos(in->getPrintableSource(), block->getLineNumber()),
749282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                             myPackage, curType, ident, str, &spans, &config,
750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                             false, curFormat, overwrite);
751282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
752282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return err;
753282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
754282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
755282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t compileResourceFile(Bundle* bundle,
756282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                             const sp<AaptAssets>& assets,
757282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                             const sp<AaptFile>& in,
758282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                             const ResTable_config& defParams,
759282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                             const bool overwrite,
760282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                             ResourceTable* outTable)
761282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
762282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ResXMLTree block;
763282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = parseXMLResource(in, &block, false, true);
764282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
765282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return err;
766282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
767282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
768282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Top-level tag.
769282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 resources16("resources");
770282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
771282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Identifier declaration tags.
772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 declare_styleable16("declare-styleable");
773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 attr16("attr");
774282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Data creation organizational tags.
776282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 string16("string");
777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 drawable16("drawable");
778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 color16("color");
779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 bool16("bool");
780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 integer16("integer");
781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 dimen16("dimen");
782282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 fraction16("fraction");
783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 style16("style");
784282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 plurals16("plurals");
785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 array16("array");
786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 string_array16("string-array");
787282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 integer_array16("integer-array");
788282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 public16("public");
789282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 public_padding16("public-padding");
790282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 private_symbols16("private-symbols");
791282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 java_symbol16("java-symbol");
792282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 add_resource16("add-resource");
793282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 skip16("skip");
794282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 eat_comment16("eat-comment");
795282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
796282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Data creation tags.
797282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 bag16("bag");
798282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 item16("item");
799282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Attribute type constants.
801282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 enum16("enum");
802282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
803282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // plural values
804282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 other16("other");
805282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 quantityOther16("^other");
806282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 zero16("zero");
807282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 quantityZero16("^zero");
808282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 one16("one");
809282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 quantityOne16("^one");
810282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 two16("two");
811282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 quantityTwo16("^two");
812282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 few16("few");
813282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 quantityFew16("^few");
814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 many16("many");
815282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 quantityMany16("^many");
816282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
817282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // useful attribute names and special values
818282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 name16("name");
819282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 translatable16("translatable");
820282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 formatted16("formatted");
821282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 false16("false");
822282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
823282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 myPackage(assets->getPackage());
824282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
825282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool hasErrors = false;
826282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
827282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool fileIsTranslatable = true;
828282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (strstr(in->getPrintableSource().string(), "donottranslate") != NULL) {
829282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fileIsTranslatable = false;
830282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
831282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
832282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    DefaultKeyedVector<String16, uint32_t> nextPublicId(0);
833282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
8348ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    // Stores the resource names that were skipped. Typically this happens when
8358ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    // AAPT is invoked without a product specified and a resource has no
8368ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    // 'default' product attribute.
8378ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    KeyedVector<type_ident_pair_t, bool> skippedResourceNames;
8388ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski
839282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ResXMLTree::event_code_t code;
840282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    do {
841282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        code = block.next();
842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } while (code == ResXMLTree::START_NAMESPACE);
843282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
844282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t len;
845282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (code != ResXMLTree::START_TAG) {
846282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
847282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                "No start tag found\n");
848282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
849282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
850282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (strcmp16(block.getElementName(&len), resources16.string()) != 0) {
851282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                "Invalid start tag %s\n", String8(block.getElementName(&len)).string());
853282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
854282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
855282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
856282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ResTable_config curParams(defParams);
857282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
858282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ResTable_config pseudoParams(curParams);
859a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        pseudoParams.language[0] = 'e';
860a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        pseudoParams.language[1] = 'n';
861a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        pseudoParams.country[0] = 'X';
862a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        pseudoParams.country[1] = 'A';
863a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin
864a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin    ResTable_config pseudoBidiParams(curParams);
865a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        pseudoBidiParams.language[0] = 'a';
866a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        pseudoBidiParams.language[1] = 'r';
867a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        pseudoBidiParams.country[0] = 'X';
868a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        pseudoBidiParams.country[1] = 'B';
869282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
87047843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk    // We should skip resources for pseudolocales if they were
87147843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk    // already added automatically. This is a fix for a transition period when
87247843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk    // manually pseudolocalized resources may be expected.
87347843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk    // TODO: remove this check after next SDK version release.
87447843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk    if ((bundle->getPseudolocalize() & PSEUDO_ACCENTED &&
87547843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk         curParams.locale == pseudoParams.locale) ||
87647843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk        (bundle->getPseudolocalize() & PSEUDO_BIDI &&
87747843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk         curParams.locale == pseudoBidiParams.locale)) {
87847843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk        SourcePos(in->getPrintableSource(), 0).warning(
87947843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk                "Resource file %s is skipped as pseudolocalization"
88047843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk                " was done automatically.",
88147843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk                in->getPrintableSource().string());
88247843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk        return NO_ERROR;
88347843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk    }
88447843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk
885282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
886282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (code == ResXMLTree::START_TAG) {
887282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const String16* curTag = NULL;
888282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String16 curType;
889282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int32_t curFormat = ResTable_map::TYPE_ANY;
890282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool curIsBag = false;
891282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool curIsBagReplaceOnOverwrite = false;
892282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool curIsStyled = false;
893282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool curIsPseudolocalizable = false;
894282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool curIsFormatted = fileIsTranslatable;
895282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool localHasErrors = false;
896282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
897282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (strcmp16(block.getElementName(&len), skip16.string()) == 0) {
898282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                while ((code=block.next()) != ResXMLTree::END_DOCUMENT
899282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        && code != ResXMLTree::BAD_DOCUMENT) {
900282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (code == ResXMLTree::END_TAG) {
901282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(block.getElementName(&len), skip16.string()) == 0) {
902282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            break;
903282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
904282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
905282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
906282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
907282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
908282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), eat_comment16.string()) == 0) {
909282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                while ((code=block.next()) != ResXMLTree::END_DOCUMENT
910282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        && code != ResXMLTree::BAD_DOCUMENT) {
911282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (code == ResXMLTree::END_TAG) {
912282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(block.getElementName(&len), eat_comment16.string()) == 0) {
913282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            break;
914282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
915282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
916282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
917282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
918282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
919282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), public16.string()) == 0) {
920282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos srcPos(in->getPrintableSource(), block.getLineNumber());
921282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
922282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 type;
923282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t typeIdx = block.indexOfAttribute(NULL, "type");
924282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (typeIdx < 0) {
925282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("A 'type' attribute is required for <public>\n");
926282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
927282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
928282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                type = String16(block.getAttributeStringValue(typeIdx, &len));
929282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
930282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 name;
931282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t nameIdx = block.indexOfAttribute(NULL, "name");
932282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (nameIdx < 0) {
933282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("A 'name' attribute is required for <public>\n");
934282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
935282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
936282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                name = String16(block.getAttributeStringValue(nameIdx, &len));
937282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
938282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                uint32_t ident = 0;
939282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t identIdx = block.indexOfAttribute(NULL, "id");
940282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (identIdx >= 0) {
941282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    const char16_t* identStr = block.getAttributeStringValue(identIdx, &len);
942282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    Res_value identValue;
943282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (!ResTable::stringToInt(identStr, len, &identValue)) {
944282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        srcPos.error("Given 'id' attribute is not an integer: %s\n",
945282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                String8(block.getAttributeStringValue(identIdx, &len)).string());
946282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasErrors = localHasErrors = true;
947282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else {
948282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ident = identValue.data;
949282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        nextPublicId.replaceValueFor(type, ident+1);
950282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
951282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else if (nextPublicId.indexOfKey(type) < 0) {
952282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("No 'id' attribute supplied <public>,"
953282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            " and no previous id defined in this file.\n");
954282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
955282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else if (!localHasErrors) {
956282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    ident = nextPublicId.valueFor(type);
957282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    nextPublicId.replaceValueFor(type, ident+1);
958282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
959282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
960282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!localHasErrors) {
961282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    err = outTable->addPublic(srcPos, myPackage, type, name, ident);
962282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (err < NO_ERROR) {
963282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasErrors = localHasErrors = true;
964282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
965282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
966282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!localHasErrors) {
967282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sp<AaptSymbols> symbols = assets->getSymbolsFor(String8("R"));
968282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (symbols != NULL) {
969282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        symbols = symbols->addNestedSymbol(String8(type), srcPos);
970282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
971282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (symbols != NULL) {
972282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        symbols->makeSymbolPublic(String8(name), srcPos);
973282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String16 comment(
974282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            block.getComment(&len) ? block.getComment(&len) : nulStr);
975282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        symbols->appendComment(String8(name), comment, srcPos);
976282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else {
977282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        srcPos.error("Unable to create symbols!\n");
978282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasErrors = localHasErrors = true;
979282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
980282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
981282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
982282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
983282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (code == ResXMLTree::END_TAG) {
984282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(block.getElementName(&len), public16.string()) == 0) {
985282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            break;
986282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
987282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
988282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
989282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
990282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
991282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), public_padding16.string()) == 0) {
992282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos srcPos(in->getPrintableSource(), block.getLineNumber());
993282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
994282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 type;
995282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t typeIdx = block.indexOfAttribute(NULL, "type");
996282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (typeIdx < 0) {
997282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("A 'type' attribute is required for <public-padding>\n");
998282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
999282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1000282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                type = String16(block.getAttributeStringValue(typeIdx, &len));
1001282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1002282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 name;
1003282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t nameIdx = block.indexOfAttribute(NULL, "name");
1004282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (nameIdx < 0) {
1005282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("A 'name' attribute is required for <public-padding>\n");
1006282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1007282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1008282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                name = String16(block.getAttributeStringValue(nameIdx, &len));
1009282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1010282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                uint32_t start = 0;
1011282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t startIdx = block.indexOfAttribute(NULL, "start");
1012282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (startIdx >= 0) {
1013282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    const char16_t* startStr = block.getAttributeStringValue(startIdx, &len);
1014282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    Res_value startValue;
1015282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (!ResTable::stringToInt(startStr, len, &startValue)) {
1016282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        srcPos.error("Given 'start' attribute is not an integer: %s\n",
1017282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                String8(block.getAttributeStringValue(startIdx, &len)).string());
1018282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasErrors = localHasErrors = true;
1019282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else {
1020282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        start = startValue.data;
1021282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1022282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else if (nextPublicId.indexOfKey(type) < 0) {
1023282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("No 'start' attribute supplied <public-padding>,"
1024282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            " and no previous id defined in this file.\n");
1025282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1026282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else if (!localHasErrors) {
1027282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    start = nextPublicId.valueFor(type);
1028282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1029282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1030282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                uint32_t end = 0;
1031282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t endIdx = block.indexOfAttribute(NULL, "end");
1032282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (endIdx >= 0) {
1033282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    const char16_t* endStr = block.getAttributeStringValue(endIdx, &len);
1034282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    Res_value endValue;
1035282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (!ResTable::stringToInt(endStr, len, &endValue)) {
1036282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        srcPos.error("Given 'end' attribute is not an integer: %s\n",
1037282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                String8(block.getAttributeStringValue(endIdx, &len)).string());
1038282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasErrors = localHasErrors = true;
1039282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else {
1040282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        end = endValue.data;
1041282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1042282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1043282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("No 'end' attribute supplied <public-padding>\n");
1044282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1045282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1046282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1047282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (end >= start) {
1048282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    nextPublicId.replaceValueFor(type, end+1);
1049282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1050282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("Padding start '%ul' is after end '%ul'\n",
1051282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            start, end);
1052282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1053282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1054282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1055282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 comment(
1056282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    block.getComment(&len) ? block.getComment(&len) : nulStr);
1057282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                for (uint32_t curIdent=start; curIdent<=end; curIdent++) {
1058282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (localHasErrors) {
1059282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        break;
1060282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1061282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String16 curName(name);
1062282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    char buf[64];
1063282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sprintf(buf, "%d", (int)(end-curIdent+1));
1064282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    curName.append(String16(buf));
1065282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1066282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    err = outTable->addEntry(srcPos, myPackage, type, curName,
1067282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                             String16("padding"), NULL, &curParams, false,
1068282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                             ResTable_map::TYPE_STRING, overwrite);
1069282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (err < NO_ERROR) {
1070282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasErrors = localHasErrors = true;
1071282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        break;
1072282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1073282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    err = outTable->addPublic(srcPos, myPackage, type,
1074282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            curName, curIdent);
1075282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (err < NO_ERROR) {
1076282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasErrors = localHasErrors = true;
1077282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        break;
1078282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1079282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sp<AaptSymbols> symbols = assets->getSymbolsFor(String8("R"));
1080282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (symbols != NULL) {
1081282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        symbols = symbols->addNestedSymbol(String8(type), srcPos);
1082282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1083282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (symbols != NULL) {
1084282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        symbols->makeSymbolPublic(String8(curName), srcPos);
1085282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        symbols->appendComment(String8(curName), comment, srcPos);
1086282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else {
1087282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        srcPos.error("Unable to create symbols!\n");
1088282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasErrors = localHasErrors = true;
1089282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1090282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1091282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1092282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
1093282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (code == ResXMLTree::END_TAG) {
1094282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(block.getElementName(&len), public_padding16.string()) == 0) {
1095282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            break;
1096282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1097282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1098282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1099282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
1100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), private_symbols16.string()) == 0) {
1102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 pkg;
1103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t pkgIdx = block.indexOfAttribute(NULL, "package");
1104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (pkgIdx < 0) {
1105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            "A 'package' attribute is required for <private-symbols>\n");
1107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                pkg = String16(block.getAttributeStringValue(pkgIdx, &len));
1110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!localHasErrors) {
1111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    assets->setSymbolsPrivatePackage(String8(pkg));
1112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
1115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (code == ResXMLTree::END_TAG) {
1116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(block.getElementName(&len), private_symbols16.string()) == 0) {
1117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            break;
1118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
1122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), java_symbol16.string()) == 0) {
1124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos srcPos(in->getPrintableSource(), block.getLineNumber());
1125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 type;
1127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t typeIdx = block.indexOfAttribute(NULL, "type");
1128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (typeIdx < 0) {
1129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("A 'type' attribute is required for <public>\n");
1130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                type = String16(block.getAttributeStringValue(typeIdx, &len));
1133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 name;
1135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t nameIdx = block.indexOfAttribute(NULL, "name");
1136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (nameIdx < 0) {
1137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("A 'name' attribute is required for <public>\n");
1138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                name = String16(block.getAttributeStringValue(nameIdx, &len));
1141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<AaptSymbols> symbols = assets->getJavaSymbolsFor(String8("R"));
1143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (symbols != NULL) {
1144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    symbols = symbols->addNestedSymbol(String8(type), srcPos);
1145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (symbols != NULL) {
1147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    symbols->makeSymbolJavaSymbol(String8(name), srcPos);
1148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String16 comment(
1149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        block.getComment(&len) ? block.getComment(&len) : nulStr);
1150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    symbols->appendComment(String8(name), comment, srcPos);
1151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("Unable to create symbols!\n");
1153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
1157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (code == ResXMLTree::END_TAG) {
1158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(block.getElementName(&len), java_symbol16.string()) == 0) {
1159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            break;
1160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
1164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), add_resource16.string()) == 0) {
1167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos srcPos(in->getPrintableSource(), block.getLineNumber());
1168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 typeName;
1170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t typeIdx = block.indexOfAttribute(NULL, "type");
1171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (typeIdx < 0) {
1172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("A 'type' attribute is required for <add-resource>\n");
1173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                typeName = String16(block.getAttributeStringValue(typeIdx, &len));
1176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 name;
1178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t nameIdx = block.indexOfAttribute(NULL, "name");
1179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (nameIdx < 0) {
1180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("A 'name' attribute is required for <add-resource>\n");
1181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                name = String16(block.getAttributeStringValue(nameIdx, &len));
1184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                outTable->canAddEntry(srcPos, myPackage, typeName, name);
1186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
1188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (code == ResXMLTree::END_TAG) {
1189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(block.getElementName(&len), add_resource16.string()) == 0) {
1190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            break;
1191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
1195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), declare_styleable16.string()) == 0) {
1197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos srcPos(in->getPrintableSource(), block.getLineNumber());
1198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 ident;
1200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t identIdx = block.indexOfAttribute(NULL, "name");
1201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (identIdx < 0) {
1202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("A 'name' attribute is required for <declare-styleable>\n");
1203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ident = String16(block.getAttributeStringValue(identIdx, &len));
1206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<AaptSymbols> symbols = assets->getSymbolsFor(String8("R"));
1208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!localHasErrors) {
1209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (symbols != NULL) {
1210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        symbols = symbols->addNestedSymbol(String8("styleable"), srcPos);
1211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sp<AaptSymbols> styleSymbols = symbols;
1213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (symbols != NULL) {
1214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        symbols = symbols->addNestedSymbol(String8(ident), srcPos);
1215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (symbols == NULL) {
1217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        srcPos.error("Unable to create symbols!\n");
1218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        return UNKNOWN_ERROR;
1219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String16 comment(
1222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        block.getComment(&len) ? block.getComment(&len) : nulStr);
1223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    styleSymbols->appendComment(String8(ident), comment, srcPos);
1224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    symbols = NULL;
1226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
1229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (code == ResXMLTree::START_TAG) {
1230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(block.getElementName(&len), skip16.string()) == 0) {
1231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            while ((code=block.next()) != ResXMLTree::END_DOCUMENT
1232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                   && code != ResXMLTree::BAD_DOCUMENT) {
1233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                if (code == ResXMLTree::END_TAG) {
1234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    if (strcmp16(block.getElementName(&len), skip16.string()) == 0) {
1235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        break;
1236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    }
1237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                }
1238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            continue;
1240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else if (strcmp16(block.getElementName(&len), eat_comment16.string()) == 0) {
1241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            while ((code=block.next()) != ResXMLTree::END_DOCUMENT
1242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                   && code != ResXMLTree::BAD_DOCUMENT) {
1243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                if (code == ResXMLTree::END_TAG) {
1244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    if (strcmp16(block.getElementName(&len), eat_comment16.string()) == 0) {
1245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        break;
1246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    }
1247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                }
1248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            continue;
1250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else if (strcmp16(block.getElementName(&len), attr16.string()) != 0) {
1251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    "Tag <%s> can not appear inside <declare-styleable>, only <attr>\n",
1253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    String8(block.getElementName(&len)).string());
1254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            return UNKNOWN_ERROR;
1255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String16 comment(
1258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            block.getComment(&len) ? block.getComment(&len) : nulStr);
1259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String16 itemIdent;
1260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        err = compileAttribute(in, block, myPackage, outTable, &itemIdent, true);
1261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (err != NO_ERROR) {
1262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            hasErrors = localHasErrors = true;
1263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (symbols != NULL) {
1266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            SourcePos srcPos(String8(in->getPrintableSource()), block.getLineNumber());
1267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            symbols->addSymbol(String8(itemIdent), 0, srcPos);
1268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            symbols->appendComment(String8(itemIdent), comment, srcPos);
1269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            //printf("Attribute %s comment: %s\n", String8(itemIdent).string(),
1270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            //     String8(comment).string());
1271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (code == ResXMLTree::END_TAG) {
1273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(block.getElementName(&len), declare_styleable16.string()) == 0) {
1274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            break;
1275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                "Found tag </%s> where </attr> is expected\n",
1279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                String8(block.getElementName(&len)).string());
1280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        return UNKNOWN_ERROR;
1281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
1284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), attr16.string()) == 0) {
1286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                err = compileAttribute(in, block, myPackage, outTable, NULL);
1287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (err != NO_ERROR) {
1288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = true;
1289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
1291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), item16.string()) == 0) {
1293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &item16;
1294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t attri = block.indexOfAttribute(NULL, "type");
1295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (attri >= 0) {
1296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    curType = String16(block.getAttributeStringValue(attri, &len));
1297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    ssize_t formatIdx = block.indexOfAttribute(NULL, "format");
1298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (formatIdx >= 0) {
1299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String16 formatStr = String16(block.getAttributeStringValue(
1300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                formatIdx, &len));
1301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        curFormat = parse_flags(formatStr.string(), formatStr.size(),
1302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                gFormatFlags);
1303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (curFormat == 0) {
1304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    "Tag <item> 'format' attribute value \"%s\" not valid\n",
1306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    String8(formatStr).string());
1307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            hasErrors = localHasErrors = true;
1308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            "A 'type' attribute is required for <item>\n");
1313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsStyled = true;
1316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), string16.string()) == 0) {
1317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Note the existence and locale of every string we process
131891447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath                char rawLocale[RESTABLE_MAX_LOCALE_LEN];
131991447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath                curParams.getBcp47Locale(rawLocale);
1320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String8 locale(rawLocale);
1321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 name;
1322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 translatable;
1323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 formatted;
1324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                size_t n = block.getAttributeCount();
1326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                for (size_t i = 0; i < n; i++) {
1327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    size_t length;
1328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    const uint16_t* attr = block.getAttributeName(i, &length);
1329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (strcmp16(attr, name16.string()) == 0) {
1330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        name.setTo(block.getAttributeStringValue(i, &length));
1331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (strcmp16(attr, translatable16.string()) == 0) {
1332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        translatable.setTo(block.getAttributeStringValue(i, &length));
1333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (strcmp16(attr, formatted16.string()) == 0) {
1334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        formatted.setTo(block.getAttributeStringValue(i, &length));
1335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (name.size() > 0) {
1339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (translatable == false16) {
1340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        curIsFormatted = false;
1341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        // Untranslatable strings must only exist in the default [empty] locale
1342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (locale.size() > 0) {
1343a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                            SourcePos(in->getPrintableSource(), block.getLineNumber()).warning(
1344a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                                    "string '%s' marked untranslatable but exists in locale '%s'\n",
1345a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                                    String8(name).string(),
1346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    locale.string());
1347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            // hasErrors = localHasErrors = true;
1348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else {
1349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            // Intentionally empty block:
1350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            //
1351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            // Don't add untranslatable strings to the localization table; that
1352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            // way if we later see localizations of them, they'll be flagged as
1353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            // having no default translation.
1354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else {
1356a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                        outTable->addLocalization(
1357a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                                name,
1358a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                                locale,
1359a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                                SourcePos(in->getPrintableSource(), block.getLineNumber()));
1360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (formatted == false16) {
1363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        curIsFormatted = false;
1364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &string16;
1368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = string16;
1369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_STRING;
1370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsStyled = true;
137184410b054c7db0b6685a0f15cb2d1ffcb264f6c9Igor Viarheichyk                curIsPseudolocalizable = fileIsTranslatable && (translatable != false16);
1372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), drawable16.string()) == 0) {
1373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &drawable16;
1374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = drawable16;
1375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_COLOR;
1376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), color16.string()) == 0) {
1377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &color16;
1378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = color16;
1379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_COLOR;
1380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), bool16.string()) == 0) {
1381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &bool16;
1382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = bool16;
1383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_BOOLEAN;
1384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), integer16.string()) == 0) {
1385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &integer16;
1386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = integer16;
1387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_INTEGER;
1388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), dimen16.string()) == 0) {
1389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &dimen16;
1390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = dimen16;
1391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_DIMENSION;
1392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), fraction16.string()) == 0) {
1393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &fraction16;
1394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = fraction16;
1395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_FRACTION;
1396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), bag16.string()) == 0) {
1397282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &bag16;
1398282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsBag = true;
1399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t attri = block.indexOfAttribute(NULL, "type");
1400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (attri >= 0) {
1401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    curType = String16(block.getAttributeStringValue(attri, &len));
1402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            "A 'type' attribute is required for <bag>\n");
1405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), style16.string()) == 0) {
1408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &style16;
1409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = style16;
1410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsBag = true;
1411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), plurals16.string()) == 0) {
1412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &plurals16;
1413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = plurals16;
1414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsBag = true;
1415a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                curIsPseudolocalizable = fileIsTranslatable;
1416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), array16.string()) == 0) {
1417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &array16;
1418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = array16;
1419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsBag = true;
1420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsBagReplaceOnOverwrite = true;
1421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t formatIdx = block.indexOfAttribute(NULL, "format");
1422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (formatIdx >= 0) {
1423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String16 formatStr = String16(block.getAttributeStringValue(
1424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            formatIdx, &len));
1425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    curFormat = parse_flags(formatStr.string(), formatStr.size(),
1426282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                            gFormatFlags);
1427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (curFormat == 0) {
1428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                "Tag <array> 'format' attribute value \"%s\" not valid\n",
1430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                String8(formatStr).string());
1431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasErrors = localHasErrors = true;
1432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1434282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), string_array16.string()) == 0) {
1435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Check whether these strings need valid formats.
1436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // (simplified form of what string16 does above)
1437a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                bool isTranslatable = false;
1438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                size_t n = block.getAttributeCount();
14399a9fa163c384e7fff159d339dfcce3b3122bece5Narayan Kamath
14409a9fa163c384e7fff159d339dfcce3b3122bece5Narayan Kamath                // Pseudolocalizable by default, unless this string array isn't
14419a9fa163c384e7fff159d339dfcce3b3122bece5Narayan Kamath                // translatable.
1442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                for (size_t i = 0; i < n; i++) {
1443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    size_t length;
1444282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    const uint16_t* attr = block.getAttributeName(i, &length);
1445a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                    if (strcmp16(attr, formatted16.string()) == 0) {
14469a9fa163c384e7fff159d339dfcce3b3122bece5Narayan Kamath                        const uint16_t* value = block.getAttributeStringValue(i, &length);
14479a9fa163c384e7fff159d339dfcce3b3122bece5Narayan Kamath                        if (strcmp16(value, false16.string()) == 0) {
1448a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                            curIsFormatted = false;
14499a9fa163c384e7fff159d339dfcce3b3122bece5Narayan Kamath                        }
1450a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                    } else if (strcmp16(attr, translatable16.string()) == 0) {
1451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const uint16_t* value = block.getAttributeStringValue(i, &length);
1452282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(value, false16.string()) == 0) {
1453a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                            isTranslatable = false;
1454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &string_array16;
1459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = array16;
1460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_STRING;
1461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsBag = true;
1462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsBagReplaceOnOverwrite = true;
1463a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                curIsPseudolocalizable = isTranslatable && fileIsTranslatable;
1464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), integer_array16.string()) == 0) {
1465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &integer_array16;
1466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = array16;
1467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_INTEGER;
1468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsBag = true;
1469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsBagReplaceOnOverwrite = true;
1470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
1471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "Found tag %s where item is expected\n",
1473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8(block.getElementName(&len)).string());
1474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return UNKNOWN_ERROR;
1475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String16 ident;
1478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ssize_t identIdx = block.indexOfAttribute(NULL, "name");
1479282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (identIdx >= 0) {
1480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ident = String16(block.getAttributeStringValue(identIdx, &len));
1481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
1482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "A 'name' attribute is required for <%s>\n",
1484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8(*curTag).string());
1485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                hasErrors = localHasErrors = true;
1486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String16 product;
1489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            identIdx = block.indexOfAttribute(NULL, "product");
1490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (identIdx >= 0) {
1491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                product = String16(block.getAttributeStringValue(identIdx, &len));
1492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String16 comment(block.getComment(&len) ? block.getComment(&len) : nulStr);
1495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (curIsBag) {
1497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Figure out the parent of this bag...
1498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 parentIdent;
1499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t parentIdentIdx = block.indexOfAttribute(NULL, "parent");
1500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (parentIdentIdx >= 0) {
1501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    parentIdent = String16(block.getAttributeStringValue(parentIdentIdx, &len));
1502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    ssize_t sep = ident.findLast('.');
1504282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (sep >= 0) {
1505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        parentIdent.setTo(ident, sep);
1506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1507282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1508282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1509282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!localHasErrors) {
1510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    err = outTable->startBag(SourcePos(in->getPrintableSource(),
1511282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            block.getLineNumber()), myPackage, curType, ident,
1512282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            parentIdent, &curParams,
1513282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            overwrite, curIsBagReplaceOnOverwrite);
1514282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (err != NO_ERROR) {
1515282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasErrors = localHasErrors = true;
1516282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1517282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1518282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1519282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t elmIndex = 0;
1520282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                char elmIndexStr[14];
1521282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                while ((code=block.next()) != ResXMLTree::END_DOCUMENT
1522282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        && code != ResXMLTree::BAD_DOCUMENT) {
1523282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1524282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (code == ResXMLTree::START_TAG) {
1525282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(block.getElementName(&len), item16.string()) != 0) {
1526282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1527282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    "Tag <%s> can not appear inside <%s>, only <item>\n",
1528282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    String8(block.getElementName(&len)).string(),
1529282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    String8(*curTag).string());
1530282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            return UNKNOWN_ERROR;
1531282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1532282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1533282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String16 itemIdent;
1534282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (curType == array16) {
1535282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            sprintf(elmIndexStr, "^index_%d", (int)elmIndex++);
1536282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            itemIdent = String16(elmIndexStr);
1537282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else if (curType == plurals16) {
1538282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            ssize_t itemIdentIdx = block.indexOfAttribute(NULL, "quantity");
1539282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (itemIdentIdx >= 0) {
1540282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                String16 quantity16(block.getAttributeStringValue(itemIdentIdx, &len));
1541282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                if (quantity16 == other16) {
1542282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    itemIdent = quantityOther16;
1543282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                }
1544282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                else if (quantity16 == zero16) {
1545282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    itemIdent = quantityZero16;
1546282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                }
1547282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                else if (quantity16 == one16) {
1548282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    itemIdent = quantityOne16;
1549282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                }
1550282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                else if (quantity16 == two16) {
1551282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    itemIdent = quantityTwo16;
1552282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                }
1553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                else if (quantity16 == few16) {
1554282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    itemIdent = quantityFew16;
1555282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                }
1556282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                else if (quantity16 == many16) {
1557282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    itemIdent = quantityMany16;
1558282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                }
1559282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                else {
1560282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1561282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                            "Illegal 'quantity' attribute is <item> inside <plurals>\n");
1562282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    hasErrors = localHasErrors = true;
1563282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                }
1564282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else {
1565282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1566282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        "A 'quantity' attribute is required for <item> inside <plurals>\n");
1567282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasErrors = localHasErrors = true;
1568282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1569282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else {
1570282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            ssize_t itemIdentIdx = block.indexOfAttribute(NULL, "name");
1571282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (itemIdentIdx >= 0) {
1572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                itemIdent = String16(block.getAttributeStringValue(itemIdentIdx, &len));
1573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else {
1574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        "A 'name' attribute is required for <item>\n");
1576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasErrors = localHasErrors = true;
1577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ResXMLParser::ResXMLPosition parserPosition;
1581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        block.getPosition(&parserPosition);
1582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        err = parseAndAddBag(bundle, in, &block, curParams, myPackage, curType,
1584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                ident, parentIdent, itemIdent, curFormat, curIsFormatted,
1585a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                product, NO_PSEUDOLOCALIZATION, overwrite, outTable);
1586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (err == NO_ERROR) {
1587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (curIsPseudolocalizable && localeIsDefined(curParams)
1588a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                    && bundle->getPseudolocalize() > 0) {
1589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                // pseudolocalize here
1590a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                if ((PSEUDO_ACCENTED & bundle->getPseudolocalize()) ==
1591a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                   PSEUDO_ACCENTED) {
1592a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                    block.setPosition(parserPosition);
1593a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                    err = parseAndAddBag(bundle, in, &block, pseudoParams, myPackage,
1594a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                            curType, ident, parentIdent, itemIdent, curFormat,
1595a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                            curIsFormatted, product, PSEUDO_ACCENTED,
1596a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                            overwrite, outTable);
1597a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                }
1598a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                if ((PSEUDO_BIDI & bundle->getPseudolocalize()) ==
1599a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                   PSEUDO_BIDI) {
1600a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                    block.setPosition(parserPosition);
1601a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                    err = parseAndAddBag(bundle, in, &block, pseudoBidiParams, myPackage,
1602a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                            curType, ident, parentIdent, itemIdent, curFormat,
1603a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                            curIsFormatted, product, PSEUDO_BIDI,
1604a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                            overwrite, outTable);
1605a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                }
1606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1607a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                        }
1608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (err != NO_ERROR) {
1609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            hasErrors = localHasErrors = true;
1610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (code == ResXMLTree::END_TAG) {
1612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(block.getElementName(&len), curTag->string()) != 0) {
1613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    "Found tag </%s> where </%s> is expected\n",
1615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    String8(block.getElementName(&len)).string(),
1616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    String8(*curTag).string());
1617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            return UNKNOWN_ERROR;
1618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        break;
1620282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
1623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ResXMLParser::ResXMLPosition parserPosition;
1624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                block.getPosition(&parserPosition);
1625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1626282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                err = parseAndAddEntry(bundle, in, &block, curParams, myPackage, curType, ident,
1627282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        *curTag, curIsStyled, curFormat, curIsFormatted,
1628a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                        product, NO_PSEUDOLOCALIZATION, overwrite, &skippedResourceNames, outTable);
1629282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1630282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (err < NO_ERROR) { // Why err < NO_ERROR instead of err != NO_ERROR?
1631282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1632282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1633282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                else if (err == NO_ERROR) {
1634282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (curIsPseudolocalizable && localeIsDefined(curParams)
1635a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                            && bundle->getPseudolocalize() > 0) {
1636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        // pseudolocalize here
1637a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                        if ((PSEUDO_ACCENTED & bundle->getPseudolocalize()) ==
1638a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                           PSEUDO_ACCENTED) {
1639a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                            block.setPosition(parserPosition);
1640a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                            err = parseAndAddEntry(bundle, in, &block, pseudoParams, myPackage, curType,
1641a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                    ident, *curTag, curIsStyled, curFormat,
1642a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                    curIsFormatted, product,
1643a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                    PSEUDO_ACCENTED, overwrite, &skippedResourceNames, outTable);
1644a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                        }
1645a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                        if ((PSEUDO_BIDI & bundle->getPseudolocalize()) ==
1646a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                           PSEUDO_BIDI) {
1647a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                            block.setPosition(parserPosition);
1648a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                            err = parseAndAddEntry(bundle, in, &block, pseudoBidiParams,
1649a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                    myPackage, curType, ident, *curTag, curIsStyled, curFormat,
1650a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                    curIsFormatted, product,
1651a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                    PSEUDO_BIDI, overwrite, &skippedResourceNames, outTable);
1652a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                        }
1653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (err != NO_ERROR) {
1654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            hasErrors = localHasErrors = true;
1655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#if 0
1661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (comment.size() > 0) {
1662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("Comment for @%s:%s/%s: %s\n", String8(myPackage).string(),
1663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       String8(curType).string(), String8(ident).string(),
1664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       String8(comment).string());
1665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif
1667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!localHasErrors) {
1668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                outTable->appendComment(myPackage, curType, ident, comment, false);
1669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        else if (code == ResXMLTree::END_TAG) {
1672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (strcmp16(block.getElementName(&len), resources16.string()) != 0) {
1673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "Unexpected end tag %s\n", String8(block.getElementName(&len)).string());
1675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return UNKNOWN_ERROR;
1676282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1677282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        else if (code == ResXMLTree::START_NAMESPACE || code == ResXMLTree::END_NAMESPACE) {
1679282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1680282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        else if (code == ResXMLTree::TEXT) {
1681282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (isWhitespace(block.getText(&len))) {
1682282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
1683282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1684282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1685282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    "Found text \"%s\" where item tag is expected\n",
1686282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(block.getText(&len)).string());
1687282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return UNKNOWN_ERROR;
1688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1690282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
16918ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    // For every resource defined, there must be exist one variant with a product attribute
16928ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    // set to 'default' (or no product attribute at all).
16938ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    // We check to see that for every resource that was ignored because of a mismatched
16948ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    // product attribute, some product variant of that resource was processed.
16958ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    for (size_t i = 0; i < skippedResourceNames.size(); i++) {
16968ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski        if (skippedResourceNames[i]) {
16978ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski            const type_ident_pair_t& p = skippedResourceNames.keyAt(i);
16988ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski            if (!outTable->hasBagOrEntry(myPackage, p.type, p.ident)) {
16998ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                const char* bundleProduct =
17008ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                        (bundle->getProduct() == NULL) ? "" : bundle->getProduct();
17018ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                fprintf(stderr, "In resource file %s: %s\n",
17028ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                        in->getPrintableSource().string(),
17038ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                        curParams.toString().string());
17048ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski
17058ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                fprintf(stderr, "\t%s '%s' does not match product %s.\n"
17068ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                        "\tYou may have forgotten to include a 'default' product variant"
17078ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                        " of the resource.\n",
17088ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                        String8(p.type).string(), String8(p.ident).string(),
17098ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                        bundleProduct[0] == 0 ? "default" : bundleProduct);
17108ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                return UNKNOWN_ERROR;
17118ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski            }
17128ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski        }
17138ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    }
17148ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski
1715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return hasErrors ? UNKNOWN_ERROR : NO_ERROR;
1716282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1717282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1718833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam LesinskiResourceTable::ResourceTable(Bundle* bundle, const String16& assetsPackage, ResourceTable::PackageType type)
1719833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    : mAssetsPackage(assetsPackage)
1720833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    , mPackageType(type)
1721833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    , mTypeIdOffset(0)
1722833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    , mNumLocal(0)
1723833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    , mBundle(bundle)
1724833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski{
1725833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    ssize_t packageId = -1;
1726833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    switch (mPackageType) {
1727833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        case App:
1728833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        case AppFeature:
1729833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            packageId = 0x7f;
1730833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            break;
1731833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski
1732833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        case System:
1733833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            packageId = 0x01;
1734833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            break;
1735833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski
1736833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        case SharedLibrary:
1737833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            packageId = 0x00;
1738833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            break;
1739833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski
1740833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        default:
1741833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            assert(0);
1742833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            break;
1743833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    }
1744833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    sp<Package> package = new Package(mAssetsPackage, packageId);
1745833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    mPackages.add(assetsPackage, package);
1746833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    mOrderedPackages.add(package);
1747833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski
1748833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    // Every resource table always has one first entry, the bag attributes.
1749833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    const SourcePos unknown(String8("????"), 0);
1750833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    getType(mAssetsPackage, String16("attr"), unknown);
1751833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski}
1752833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski
1753833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinskistatic uint32_t findLargestTypeIdForPackage(const ResTable& table, const String16& packageName) {
1754833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    const size_t basePackageCount = table.getBasePackageCount();
1755833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    for (size_t i = 0; i < basePackageCount; i++) {
1756833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        if (packageName == table.getBasePackageName(i)) {
1757833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            return table.getLastTypeIdForPackage(i);
1758833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        }
1759833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    }
1760833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    return 0;
1761282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1762282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1763282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::addIncludedResources(Bundle* bundle, const sp<AaptAssets>& assets)
1764282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1765282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = assets->buildIncludedResources(bundle);
1766282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
1767282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return err;
1768282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1769282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1770282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mAssets = assets;
1771833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    mTypeIdOffset = findLargestTypeIdForPackage(assets->getIncludedResources(), mAssetsPackage);
1772833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski
1773833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    const String8& featureAfter = bundle->getFeatureAfterPackage();
1774833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    if (!featureAfter.isEmpty()) {
1775833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        AssetManager featureAssetManager;
1776833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        if (!featureAssetManager.addAssetPath(featureAfter, NULL)) {
1777833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            fprintf(stderr, "ERROR: Feature package '%s' not found.\n",
1778833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                    featureAfter.string());
1779833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            return UNKNOWN_ERROR;
1780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1782833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        const ResTable& featureTable = featureAssetManager.getResources(false);
1783833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        mTypeIdOffset = max(mTypeIdOffset,
1784833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                findLargestTypeIdForPackage(featureTable, mAssetsPackage));
1785833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    }
1786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1787282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
1788282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1789282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1790282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::addPublic(const SourcePos& sourcePos,
1791282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16& package,
1792282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16& type,
1793282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16& name,
1794282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const uint32_t ident)
1795282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1796282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t rid = mAssets->getIncludedResources()
1797282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        .identifierForName(name.string(), name.size(),
1798282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           type.string(), type.size(),
1799282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           package.string(), package.size());
1800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (rid != 0) {
1801282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sourcePos.error("Error declaring public resource %s/%s for included package %s\n",
1802282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String8(type).string(), String8(name).string(),
1803282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String8(package).string());
1804282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
1805282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1806282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1807282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Type> t = getType(package, type, sourcePos);
1808282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (t == NULL) {
1809282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
1810282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1811282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return t->addPublic(sourcePos, name, ident);
1812282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1813282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::addEntry(const SourcePos& sourcePos,
1815282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16& package,
1816282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16& type,
1817282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16& name,
1818282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16& value,
1819282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const Vector<StringPool::entry_style_span>* style,
1820282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const ResTable_config* params,
1821282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const bool doSetIndex,
1822282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const int32_t format,
1823282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const bool overwrite)
1824282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1825282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t rid = mAssets->getIncludedResources()
1826282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        .identifierForName(name.string(), name.size(),
1827282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           type.string(), type.size(),
1828282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           package.string(), package.size());
1829282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (rid != 0) {
1830833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        sourcePos.error("Resource entry %s/%s is already defined in package %s.",
1831833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                String8(type).string(), String8(name).string(), String8(package).string());
1832833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        return UNKNOWN_ERROR;
1833282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1834282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1835282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Entry> e = getEntry(package, type, name, sourcePos, overwrite,
1836282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           params, doSetIndex);
1837282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (e == NULL) {
1838282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
1839282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1840282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = e->setItem(sourcePos, value, style, format, overwrite);
1841282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err == NO_ERROR) {
1842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mNumLocal++;
1843282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1844282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return err;
1845282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1846282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1847282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::startBag(const SourcePos& sourcePos,
1848282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16& package,
1849282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16& type,
1850282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16& name,
1851282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16& bagParent,
1852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const ResTable_config* params,
1853282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 bool overlay,
1854282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 bool replace, bool isId)
1855282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1856282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t result = NO_ERROR;
1857282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1858282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Check for adding entries in other packages...  for now we do
1859282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // nothing.  We need to do the right thing here to support skinning.
1860282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t rid = mAssets->getIncludedResources()
1861282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    .identifierForName(name.string(), name.size(),
1862282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       type.string(), type.size(),
1863282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       package.string(), package.size());
1864282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (rid != 0) {
1865833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        sourcePos.error("Resource entry %s/%s is already defined in package %s.",
1866833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                String8(type).string(), String8(name).string(), String8(package).string());
1867833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        return UNKNOWN_ERROR;
1868282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1869833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski
1870282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (overlay && !mBundle->getAutoAddOverlay() && !hasBagOrEntry(package, type, name)) {
1871282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        bool canAdd = false;
1872282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Package> p = mPackages.valueFor(package);
1873282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (p != NULL) {
1874282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<Type> t = p->getTypes().valueFor(type);
1875282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (t != NULL) {
1876282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (t->getCanAddEntries().indexOf(name) >= 0) {
1877282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    canAdd = true;
1878282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1879282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1880282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1881282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!canAdd) {
1882282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sourcePos.error("Resource does not already exist in overlay at '%s'; use <add-resource> to add.\n",
1883282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            String8(name).string());
1884282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return UNKNOWN_ERROR;
1885282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1886282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1887282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Entry> e = getEntry(package, type, name, sourcePos, overlay, params);
1888282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (e == NULL) {
1889282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
1890282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1891282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1892282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // If a parent is explicitly specified, set it.
1893282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bagParent.size() > 0) {
1894282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        e->setParent(bagParent);
1895282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1896282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1897282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if ((result = e->makeItABag(sourcePos)) != NO_ERROR) {
1898282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return result;
1899282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1900282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1901282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (overlay && replace) {
1902282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return e->emptyBag(sourcePos);
1903282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1904282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return result;
1905282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1906282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1907282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::addBag(const SourcePos& sourcePos,
1908282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                               const String16& package,
1909282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                               const String16& type,
1910282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                               const String16& name,
1911282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                               const String16& bagParent,
1912282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                               const String16& bagKey,
1913282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                               const String16& value,
1914282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                               const Vector<StringPool::entry_style_span>* style,
1915282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                               const ResTable_config* params,
1916282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                               bool replace, bool isId, const int32_t format)
1917282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1918282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Check for adding entries in other packages...  for now we do
1919282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // nothing.  We need to do the right thing here to support skinning.
1920282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t rid = mAssets->getIncludedResources()
1921282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        .identifierForName(name.string(), name.size(),
1922282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           type.string(), type.size(),
1923282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           package.string(), package.size());
1924282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (rid != 0) {
1925282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NO_ERROR;
1926282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1927282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1928282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#if 0
1929282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (name == String16("left")) {
1930282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printf("Adding bag left: file=%s, line=%d, type=%s\n",
1931282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski               sourcePos.file.striing(), sourcePos.line, String8(type).string());
1932282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1933282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif
1934282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Entry> e = getEntry(package, type, name, sourcePos, replace, params);
1935282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (e == NULL) {
1936282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
1937282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1938282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1939282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // If a parent is explicitly specified, set it.
1940282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bagParent.size() > 0) {
1941282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        e->setParent(bagParent);
1942282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1943282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1944282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const bool first = e->getBag().indexOfKey(bagKey) < 0;
1945282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = e->addToBag(sourcePos, bagKey, value, style, replace, isId, format);
1946282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err == NO_ERROR && first) {
1947282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mNumLocal++;
1948282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1949282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return err;
1950282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1951282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1952282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::hasBagOrEntry(const String16& package,
1953282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16& type,
1954282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16& name) const
1955282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1956282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // First look for this in the included resources...
1957282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t rid = mAssets->getIncludedResources()
1958282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        .identifierForName(name.string(), name.size(),
1959282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           type.string(), type.size(),
1960282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           package.string(), package.size());
1961282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (rid != 0) {
1962282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
1963282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1964282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1965282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Package> p = mPackages.valueFor(package);
1966282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (p != NULL) {
1967282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Type> t = p->getTypes().valueFor(type);
1968282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (t != NULL) {
1969282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<ConfigList> c =  t->getConfigs().valueFor(name);
1970282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (c != NULL) return true;
1971282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1972282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1973282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1974282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
1975282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1976282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1977282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::hasBagOrEntry(const String16& package,
1978282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16& type,
1979282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16& name,
1980282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const ResTable_config& config) const
1981282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1982282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // First look for this in the included resources...
1983282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t rid = mAssets->getIncludedResources()
1984282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        .identifierForName(name.string(), name.size(),
1985282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           type.string(), type.size(),
1986282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           package.string(), package.size());
1987282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (rid != 0) {
1988282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
1989282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1990282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1991282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Package> p = mPackages.valueFor(package);
1992282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (p != NULL) {
1993282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Type> t = p->getTypes().valueFor(type);
1994282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (t != NULL) {
1995282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<ConfigList> c =  t->getConfigs().valueFor(name);
1996282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (c != NULL) {
1997282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<Entry> e = c->getEntries().valueFor(config);
1998282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (e != NULL) {
1999282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return true;
2000282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2001282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2002282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2003282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2004282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2005282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
2006282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2007282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2008282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::hasBagOrEntry(const String16& ref,
2009282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16* defType,
2010282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16* defPackage)
2011282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2012282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String16 package, type, name;
2013282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (!ResTable::expandResourceRef(ref.string(), ref.size(), &package, &type, &name,
2014282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                defType, defPackage ? defPackage:&mAssetsPackage, NULL)) {
2015282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return false;
2016282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2017282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return hasBagOrEntry(package, type, name);
2018282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2019282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2020282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::appendComment(const String16& package,
2021282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16& type,
2022282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16& name,
2023282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16& comment,
2024282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  bool onlyIfEmpty)
2025282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2026282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (comment.size() <= 0) {
2027282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
2028282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2029282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2030282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Package> p = mPackages.valueFor(package);
2031282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (p != NULL) {
2032282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Type> t = p->getTypes().valueFor(type);
2033282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (t != NULL) {
2034282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<ConfigList> c =  t->getConfigs().valueFor(name);
2035282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (c != NULL) {
2036282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                c->appendComment(comment, onlyIfEmpty);
2037282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return true;
2038282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2039282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2040282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2041282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
2042282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2043282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2044282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::appendTypeComment(const String16& package,
2045282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                      const String16& type,
2046282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                      const String16& name,
2047282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                      const String16& comment)
2048282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2049282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (comment.size() <= 0) {
2050282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
2051282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2052282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2053282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Package> p = mPackages.valueFor(package);
2054282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (p != NULL) {
2055282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Type> t = p->getTypes().valueFor(type);
2056282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (t != NULL) {
2057282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<ConfigList> c =  t->getConfigs().valueFor(name);
2058282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (c != NULL) {
2059282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                c->appendTypeComment(comment);
2060282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return true;
2061282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2062282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2063282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2064282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
2065282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2066282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2067282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid ResourceTable::canAddEntry(const SourcePos& pos,
2068282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String16& package, const String16& type, const String16& name)
2069282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2070282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Type> t = getType(package, type, pos);
2071282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (t != NULL) {
2072282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        t->canAddEntry(name);
2073282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2074282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2075282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2076282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisize_t ResourceTable::size() const {
2077282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return mPackages.size();
2078282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2079282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2080282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisize_t ResourceTable::numLocalResources() const {
2081282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return mNumLocal;
2082282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2083282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2084282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::hasResources() const {
2085282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return mNumLocal > 0;
2086282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2087282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
208827f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinskisp<AaptFile> ResourceTable::flatten(Bundle* bundle, const sp<const ResourceFilter>& filter,
208927f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski        const bool isBase)
2090282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2091282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<AaptFile> data = new AaptFile(String8(), AaptGroupEntry(), String8());
209227f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski    status_t err = flatten(bundle, filter, data, isBase);
2093282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return err == NO_ERROR ? data : NULL;
2094282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2095282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2096282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiinline uint32_t ResourceTable::getResId(const sp<Package>& p,
2097282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        const sp<Type>& t,
2098282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        uint32_t nameId)
2099282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return makeResId(p->getAssignedId(), t->getIndex(), nameId);
2101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiuint32_t ResourceTable::getResId(const String16& package,
2104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16& type,
2105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16& name,
2106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 bool onlyPublic) const
2107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t id = ResourceIdCache::lookup(package, type, name, onlyPublic);
2109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (id != 0) return id;     // cache hit
2110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // First look for this in the included resources...
2112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t specFlags = 0;
2113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t rid = mAssets->getIncludedResources()
2114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        .identifierForName(name.string(), name.size(),
2115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           type.string(), type.size(),
2116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           package.string(), package.size(),
2117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           &specFlags);
2118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (rid != 0) {
2119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (onlyPublic) {
2120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if ((specFlags & ResTable_typeSpec::SPEC_PUBLIC) == 0) {
2121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return 0;
2122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2125833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        return ResourceIdCache::store(package, type, name, onlyPublic, rid);
2126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2128833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    sp<Package> p = mPackages.valueFor(package);
2129833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    if (p == NULL) return 0;
2130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Type> t = p->getTypes().valueFor(type);
2131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (t == NULL) return 0;
2132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<ConfigList> c =  t->getConfigs().valueFor(name);
2133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (c == NULL) return 0;
2134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int32_t ei = c->getEntryIndex();
2135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (ei < 0) return 0;
2136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return ResourceIdCache::store(package, type, name, onlyPublic,
2138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            getResId(p, t, ei));
2139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiuint32_t ResourceTable::getResId(const String16& ref,
2142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16* defType,
2143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16* defPackage,
2144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const char** outErrorMsg,
2145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 bool onlyPublic) const
2146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String16 package, type, name;
2148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool refOnlyPublic = true;
2149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (!ResTable::expandResourceRef(
2150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ref.string(), ref.size(), &package, &type, &name,
2151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        defType, defPackage ? defPackage:&mAssetsPackage,
2152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        outErrorMsg, &refOnlyPublic)) {
2153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        NOISY(printf("Expanding resource: ref=%s\n",
2154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                     String8(ref).string()));
2155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        NOISY(printf("Expanding resource: defType=%s\n",
2156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                     defType ? String8(*defType).string() : "NULL"));
2157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        NOISY(printf("Expanding resource: defPackage=%s\n",
2158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                     defPackage ? String8(*defPackage).string() : "NULL"));
2159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        NOISY(printf("Expanding resource: ref=%s\n", String8(ref).string()));
2160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        NOISY(printf("Expanded resource: p=%s, t=%s, n=%s, res=0\n",
2161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                     String8(package).string(), String8(type).string(),
2162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                     String8(name).string()));
2163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return 0;
2164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t res = getResId(package, type, name, onlyPublic && refOnlyPublic);
2166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    NOISY(printf("Expanded resource: p=%s, t=%s, n=%s, res=%d\n",
2167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 String8(package).string(), String8(type).string(),
2168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 String8(name).string(), res));
2169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (res == 0) {
2170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (outErrorMsg)
2171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            *outErrorMsg = "No resource found that matches the given name";
2172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return res;
2174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::isValidResourceName(const String16& s)
2177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char16_t* p = s.string();
2179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool first = true;
2180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (*p) {
2181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if ((*p >= 'a' && *p <= 'z')
2182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            || (*p >= 'A' && *p <= 'Z')
2183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            || *p == '_'
2184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            || (!first && *p >= '0' && *p <= '9')) {
2185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            first = false;
2186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            p++;
2187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
2188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return false;
2190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return true;
2192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::stringToValue(Res_value* outValue, StringPool* pool,
2195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16& str,
2196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  bool preserveSpaces, bool coerceType,
2197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  uint32_t attrID,
2198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const Vector<StringPool::entry_style_span>* style,
2199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  String16* outStr, void* accessorCookie,
2200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  uint32_t attrType, const String8* configTypeName,
2201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const ConfigDescription* config)
2202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String16 finalStr;
2204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool res = true;
2206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (style == NULL || style->size() == 0) {
2207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Text is not styled so it can be any type...  let's figure it out.
2208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        res = mAssets->getIncludedResources()
2209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            .stringToValue(outValue, &finalStr, str.string(), str.size(), preserveSpaces,
2210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            coerceType, attrID, NULL, &mAssetsPackage, this,
2211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           accessorCookie, attrType);
2212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
2213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Styled text can only be a string, and while collecting the style
2214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // information we have already processed that string!
2215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        outValue->size = sizeof(Res_value);
2216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        outValue->res0 = 0;
2217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        outValue->dataType = outValue->TYPE_STRING;
2218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        outValue->data = 0;
2219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        finalStr = str;
2220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (!res) {
2223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return false;
2224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (outValue->dataType == outValue->TYPE_STRING) {
2227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Should do better merging styles.
2228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (pool) {
2229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 configStr;
2230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (config != NULL) {
2231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                configStr = config->toString();
2232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
2233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                configStr = "(null)";
2234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            NOISY(printf("Adding to pool string style #%d config %s: %s\n",
2236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    style != NULL ? style->size() : 0,
2237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    configStr.string(), String8(finalStr).string()));
2238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (style != NULL && style->size() > 0) {
2239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                outValue->data = pool->add(finalStr, *style, configTypeName, config);
2240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
2241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                outValue->data = pool->add(finalStr, true, configTypeName, config);
2242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
2244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Caller will fill this in later.
2245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            outValue->data = 0;
2246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (outStr) {
2249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            *outStr = finalStr;
2250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return true;
2255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiuint32_t ResourceTable::getCustomResource(
2258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16& package, const String16& type, const String16& name) const
2259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //printf("getCustomResource: %s %s %s\n", String8(package).string(),
2261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //       String8(type).string(), String8(name).string());
2262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Package> p = mPackages.valueFor(package);
2263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (p == NULL) return 0;
2264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Type> t = p->getTypes().valueFor(type);
2265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (t == NULL) return 0;
2266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<ConfigList> c =  t->getConfigs().valueFor(name);
2267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (c == NULL) return 0;
2268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int32_t ei = c->getEntryIndex();
2269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (ei < 0) return 0;
2270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return getResId(p, t, ei);
2271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiuint32_t ResourceTable::getCustomResourceWithCreation(
2274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String16& package, const String16& type, const String16& name,
2275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const bool createIfNotFound)
2276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t resId = getCustomResource(package, type, name);
2278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (resId != 0 || !createIfNotFound) {
2279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return resId;
2280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2282f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski    if (mAssetsPackage != package) {
2283833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        mCurrentXmlPos.error("creating resource for external package %s: %s/%s.",
2284f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                String8(package).string(), String8(type).string(), String8(name).string());
2285833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        if (package == String16("android")) {
2286833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            mCurrentXmlPos.printf("did you mean to use @+id instead of @+android:id?");
2287833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        }
2288833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        return 0;
2289f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski    }
2290f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski
2291f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski    String16 value("false");
2292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t status = addEntry(mCurrentXmlPos, package, type, name, value, NULL, NULL, true);
2293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (status == NO_ERROR) {
2294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        resId = getResId(package, type, name);
2295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return resId;
2296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return 0;
2298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiuint32_t ResourceTable::getRemappedPackage(uint32_t origPackage) const
2301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return origPackage;
2303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::getAttributeType(uint32_t attrID, uint32_t* outType)
2306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //printf("getAttributeType #%08x\n", attrID);
2308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Res_value value;
2309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (getItemValue(attrID, ResTable_map::ATTR_TYPE, &value)) {
2310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //printf("getAttributeType #%08x (%s): #%08x\n", attrID,
2311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //       String8(getEntry(attrID)->getName()).string(), value.data);
2312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        *outType = value.data;
2313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
2314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
2316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::getAttributeMin(uint32_t attrID, uint32_t* outMin)
2319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //printf("getAttributeMin #%08x\n", attrID);
2321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Res_value value;
2322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (getItemValue(attrID, ResTable_map::ATTR_MIN, &value)) {
2323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        *outMin = value.data;
2324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
2325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
2327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::getAttributeMax(uint32_t attrID, uint32_t* outMax)
2330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //printf("getAttributeMax #%08x\n", attrID);
2332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Res_value value;
2333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (getItemValue(attrID, ResTable_map::ATTR_MAX, &value)) {
2334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        *outMax = value.data;
2335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
2336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
2338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiuint32_t ResourceTable::getAttributeL10N(uint32_t attrID)
2341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //printf("getAttributeL10N #%08x\n", attrID);
2343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Res_value value;
2344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (getItemValue(attrID, ResTable_map::ATTR_L10N, &value)) {
2345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return value.data;
2346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return ResTable_map::L10N_NOT_REQUIRED;
2348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::getLocalizationSetting()
2351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return mBundle->getRequireLocalization();
2353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid ResourceTable::reportError(void* accessorCookie, const char* fmt, ...)
2356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (accessorCookie != NULL && fmt != NULL) {
2358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        AccessorCookie* ac = (AccessorCookie*)accessorCookie;
2359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int retval=0;
2360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        char buf[1024];
2361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        va_list ap;
2362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        va_start(ap, fmt);
2363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        retval = vsnprintf(buf, sizeof(buf), fmt, ap);
2364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        va_end(ap);
2365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ac->sourcePos.error("Error: %s (at '%s' with value '%s').\n",
2366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            buf, ac->attr.string(), ac->value.string());
2367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::getAttributeKeys(
2371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t attrID, Vector<String16>* outKeys)
2372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<const Entry> e = getEntry(attrID);
2374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (e != NULL) {
2375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t N = e->getBag().size();
2376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (size_t i=0; i<N; i++) {
2377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const String16& key = e->getBag().keyAt(i);
2378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (key.size() > 0 && key.string()[0] != '^') {
2379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                outKeys->add(key);
2380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
2383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
2385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::getAttributeEnum(
2388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t attrID, const char16_t* name, size_t nameLen,
2389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Res_value* outValue)
2390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //printf("getAttributeEnum #%08x %s\n", attrID, String8(name, nameLen).string());
2392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String16 nameStr(name, nameLen);
2393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<const Entry> e = getEntry(attrID);
2394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (e != NULL) {
2395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t N = e->getBag().size();
2396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (size_t i=0; i<N; i++) {
2397282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //printf("Comparing %s to %s\n", String8(name, nameLen).string(),
2398282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //       String8(e->getBag().keyAt(i)).string());
2399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (e->getBag().keyAt(i) == nameStr) {
2400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return getItemValue(attrID, e->getBag().valueAt(i).bagKeyId, outValue);
2401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
2405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::getAttributeFlags(
2408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t attrID, const char16_t* name, size_t nameLen,
2409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Res_value* outValue)
2410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    outValue->dataType = Res_value::TYPE_INT_HEX;
2412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    outValue->data = 0;
2413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //printf("getAttributeFlags #%08x %s\n", attrID, String8(name, nameLen).string());
2415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String16 nameStr(name, nameLen);
2416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<const Entry> e = getEntry(attrID);
2417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (e != NULL) {
2418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t N = e->getBag().size();
2419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const char16_t* end = name + nameLen;
2421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const char16_t* pos = name;
2422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        while (pos < end) {
2423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const char16_t* start = pos;
2424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            while (pos < end && *pos != '|') {
2425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                pos++;
2426282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String16 nameStr(start, pos-start);
2429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            size_t i;
2430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (i=0; i<N; i++) {
2431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                //printf("Comparing \"%s\" to \"%s\"\n", String8(nameStr).string(),
2432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                //       String8(e->getBag().keyAt(i)).string());
2433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (e->getBag().keyAt(i) == nameStr) {
2434282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    Res_value val;
2435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    bool got = getItemValue(attrID, e->getBag().valueAt(i).bagKeyId, &val);
2436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (!got) {
2437282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        return false;
2438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    //printf("Got value: 0x%08x\n", val.data);
2440282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    outValue->data |= val.data;
2441282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    break;
2442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2444282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2445282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (i >= N) {
2446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Didn't find this flag identifier.
2447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return false;
2448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            pos++;
2450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2452282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
2453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
2455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::assignResourceIds()
2458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t N = mOrderedPackages.size();
2460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t pi;
2461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t firstError = NO_ERROR;
2462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // First generate all bag attributes and assign indices.
2464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (pi=0; pi<N; pi++) {
2465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Package> p = mOrderedPackages.itemAt(pi);
2466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (p == NULL || p->getTypes().size() == 0) {
2467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Empty, skip!
2468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
2469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2471833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        // This has no sense for packages being built as AppFeature (aka with a non-zero offset).
2472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        status_t err = p->applyPublicTypeOrder();
2473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != NO_ERROR && firstError == NO_ERROR) {
2474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            firstError = err;
2475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Generate attributes...
2478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t N = p->getOrderedTypes().size();
2479282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        size_t ti;
2480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (ti=0; ti<N; ti++) {
2481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<Type> t = p->getOrderedTypes().itemAt(ti);
2482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (t == NULL) {
2483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
2484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t N = t->getOrderedConfigs().size();
2486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t ci=0; ci<N; ci++) {
2487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<ConfigList> c = t->getOrderedConfigs().itemAt(ci);
2488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (c == NULL) {
2489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
2490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                const size_t N = c->getEntries().size();
2492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                for (size_t ei=0; ei<N; ei++) {
2493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sp<Entry> e = c->getEntries().valueAt(ei);
2494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (e == NULL) {
2495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        continue;
2496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    status_t err = e->generateAttributes(this, p->getName());
2498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (err != NO_ERROR && firstError == NO_ERROR) {
2499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        firstError = err;
2500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2504282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2505833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        uint32_t typeIdOffset = 0;
2506833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        if (mPackageType == AppFeature && p->getName() == mAssetsPackage) {
2507833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            typeIdOffset = mTypeIdOffset;
2508833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        }
2509833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski
2510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const SourcePos unknown(String8("????"), 0);
2511282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Type> attr = p->getType(String16("attr"), unknown);
2512282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2513282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Assign indices...
251443a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski        const size_t typeCount = p->getOrderedTypes().size();
251543a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski        for (size_t ti = 0; ti < typeCount; ti++) {
2516282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<Type> t = p->getOrderedTypes().itemAt(ti);
2517282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (t == NULL) {
2518282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
2519282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
252043a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski
2521282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            err = t->applyPublicEntryOrder();
2522282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (err != NO_ERROR && firstError == NO_ERROR) {
2523282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                firstError = err;
2524282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2525282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2526282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t N = t->getOrderedConfigs().size();
2527833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            t->setIndex(ti + 1 + typeIdOffset);
2528282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2529282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            LOG_ALWAYS_FATAL_IF(ti == 0 && attr != t,
2530282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                "First type is not attr!");
2531282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2532282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t ei=0; ei<N; ei++) {
2533282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<ConfigList> c = t->getOrderedConfigs().itemAt(ei);
2534282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (c == NULL) {
2535282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
2536282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2537282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                c->setEntryIndex(ei);
2538282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2539282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2540282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2541282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Assign resource IDs to keys in bags...
254243a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski        for (size_t ti = 0; ti < typeCount; ti++) {
2543282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<Type> t = p->getOrderedTypes().itemAt(ti);
2544282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (t == NULL) {
2545282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
2546282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2547282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t N = t->getOrderedConfigs().size();
2548282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t ci=0; ci<N; ci++) {
2549282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<ConfigList> c = t->getOrderedConfigs().itemAt(ci);
2550282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                //printf("Ordered config #%d: %p\n", ci, c.get());
2551282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                const size_t N = c->getEntries().size();
2552282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                for (size_t ei=0; ei<N; ei++) {
2553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sp<Entry> e = c->getEntries().valueAt(ei);
2554282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (e == NULL) {
2555282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        continue;
2556282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2557282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    status_t err = e->assignResourceIds(this, p->getName());
2558282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (err != NO_ERROR && firstError == NO_ERROR) {
2559282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        firstError = err;
2560282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2561282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2562282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2563282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2564282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2565282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return firstError;
2566282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2567282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2568282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::addSymbols(const sp<AaptSymbols>& outSymbols) {
2569282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t N = mOrderedPackages.size();
2570282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t pi;
2571282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (pi=0; pi<N; pi++) {
2573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Package> p = mOrderedPackages.itemAt(pi);
2574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (p->getTypes().size() == 0) {
2575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Empty, skip!
2576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
2577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t N = p->getOrderedTypes().size();
2580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        size_t ti;
2581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (ti=0; ti<N; ti++) {
2583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<Type> t = p->getOrderedTypes().itemAt(ti);
2584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (t == NULL) {
2585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
2586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t N = t->getOrderedConfigs().size();
25883fb8c9b50ef1873454acf3a4e7fd33ad182c03d7Adam Lesinski            sp<AaptSymbols> typeSymbols =
25893fb8c9b50ef1873454acf3a4e7fd33ad182c03d7Adam Lesinski                    outSymbols->addNestedSymbol(String8(t->getName()), t->getPos());
25903fb8c9b50ef1873454acf3a4e7fd33ad182c03d7Adam Lesinski            if (typeSymbols == NULL) {
25913fb8c9b50ef1873454acf3a4e7fd33ad182c03d7Adam Lesinski                return UNKNOWN_ERROR;
25923fb8c9b50ef1873454acf3a4e7fd33ad182c03d7Adam Lesinski            }
25933fb8c9b50ef1873454acf3a4e7fd33ad182c03d7Adam Lesinski
2594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t ci=0; ci<N; ci++) {
2595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<ConfigList> c = t->getOrderedConfigs().itemAt(ci);
2596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (c == NULL) {
2597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
2598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                uint32_t rid = getResId(p, t, ci);
2600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (rid == 0) {
2601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return UNKNOWN_ERROR;
2602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2603833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                if (Res_GETPACKAGE(rid) + 1 == p->getAssignedId()) {
2604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    typeSymbols->addSymbol(String8(c->getName()), rid, c->getPos());
2605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String16 comment(c->getComment());
2607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    typeSymbols->appendComment(String8(c->getName()), comment, c->getPos());
26088ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                    //printf("Type symbol [%08x] %s comment: %s\n", rid,
26098ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                    //        String8(c->getName()).string(), String8(comment).string());
2610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    comment = c->getTypeComment();
2611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    typeSymbols->appendTypeComment(String8(c->getName()), comment);
2612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
2617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2620282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid
2621a01a9374fd386f3a8773528d7a49bc5315492dffAdam LesinskiResourceTable::addLocalization(const String16& name, const String8& locale, const SourcePos& src)
2622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2623a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski    mLocalizations[name][locale] = src;
2624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2626282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2627282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*!
2628282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Flag various sorts of localization problems.  '+' indicates checks already implemented;
2629282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * '-' indicates checks that will be implemented in the future.
2630282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
2631282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * + A localized string for which no default-locale version exists => warning
2632282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * + A string for which no version in an explicitly-requested locale exists => warning
2633282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * + A localized translation of an translateable="false" string => warning
2634282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * - A localized string not provided in every locale used by the table
2635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
2636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t
2637282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiResourceTable::validateLocalizations(void)
2638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = NO_ERROR;
2640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String8 defaultLocale;
2641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // For all strings...
2643a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski    for (map<String16, map<String8, SourcePos> >::iterator nameIter = mLocalizations.begin();
2644282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         nameIter != mLocalizations.end();
2645282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         nameIter++) {
2646a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski        const map<String8, SourcePos>& configSrcMap = nameIter->second;
2647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2648282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Look for strings with no default localization
2649a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski        if (configSrcMap.count(defaultLocale) == 0) {
2650a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski            SourcePos().warning("string '%s' has no default translation.",
2651a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                    String8(nameIter->first).string());
2652a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski            if (mBundle->getVerbose()) {
2653a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                for (map<String8, SourcePos>::const_iterator locales = configSrcMap.begin();
2654a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                    locales != configSrcMap.end();
2655a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                    locales++) {
2656a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                    locales->second.printf("locale %s found", locales->first.string());
2657a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                }
2658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // !!! TODO: throw an error here in some circumstances
2660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Check that all requested localizations are present for this string
2663fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        if (mBundle->getConfigurations().size() > 0 && mBundle->getRequireLocalization()) {
2664fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            const char* allConfigs = mBundle->getConfigurations().string();
2665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const char* start = allConfigs;
2666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const char* comma;
2667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2668a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski            set<String8> missingConfigs;
2669a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski            AaptLocaleValue locale;
2670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            do {
2671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String8 config;
2672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                comma = strchr(start, ',');
2673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (comma != NULL) {
2674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    config.setTo(start, comma - start);
2675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    start = comma + 1;
2676282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
2677282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    config.setTo(start);
2678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2679282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2680a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                if (!locale.initFromFilterString(config)) {
2681a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                    continue;
2682a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                }
2683a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski
2684a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                // don't bother with the pseudolocale "en_XA" or "ar_XB"
2685a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                if (config != "en_XA" && config != "ar_XB") {
2686a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                    if (configSrcMap.find(config) == configSrcMap.end()) {
2687282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        // okay, no specific localization found.  it's possible that we are
2688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        // requiring a specific regional localization [e.g. de_DE] but there is an
2689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        // available string in the generic language localization [e.g. de];
2690282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        // consider that string to have fulfilled the localization requirement.
2691282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8 region(config.string(), 2);
2692a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                        if (configSrcMap.find(region) == configSrcMap.end() &&
2693a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                                configSrcMap.count(defaultLocale) == 0) {
2694a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                            missingConfigs.insert(config);
2695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
2696282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2698a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski            } while (comma != NULL);
2699a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski
2700a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski            if (!missingConfigs.empty()) {
2701a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                String8 configStr;
2702a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                for (set<String8>::iterator iter = missingConfigs.begin();
2703a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                     iter != missingConfigs.end();
2704a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                     iter++) {
2705a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                    configStr.appendFormat(" %s", iter->string());
2706a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                }
2707a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                SourcePos().warning("string '%s' is missing %u required localizations:%s",
2708a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                        String8(nameIter->first).string(),
2709a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                        (unsigned int)missingConfigs.size(),
2710a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                        configStr.string());
2711a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski            }
2712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2714282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return err;
2716282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2717282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
271827f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinskistatus_t ResourceTable::flatten(Bundle* bundle, const sp<const ResourceFilter>& filter,
271927f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski        const sp<AaptFile>& dest,
272027f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski        const bool isBase)
2721282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2722282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const ConfigDescription nullConfig;
2723282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2724282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t N = mOrderedPackages.size();
2725282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t pi;
2726282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2727282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const static String16 mipmap16("mipmap");
2728282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2729282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool useUTF8 = !bundle->getUTF16StringsOption();
2730282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2731de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski    // The libraries this table references.
2732de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski    Vector<sp<Package> > libraryPackages;
27336022debdbcc4498736580640c6287b57872617a2Adam Lesinski    const ResTable& table = mAssets->getIncludedResources();
27346022debdbcc4498736580640c6287b57872617a2Adam Lesinski    const size_t basePackageCount = table.getBasePackageCount();
27356022debdbcc4498736580640c6287b57872617a2Adam Lesinski    for (size_t i = 0; i < basePackageCount; i++) {
27366022debdbcc4498736580640c6287b57872617a2Adam Lesinski        size_t packageId = table.getBasePackageId(i);
27376022debdbcc4498736580640c6287b57872617a2Adam Lesinski        String16 packageName(table.getBasePackageName(i));
27386022debdbcc4498736580640c6287b57872617a2Adam Lesinski        if (packageId > 0x01 && packageId != 0x7f &&
27396022debdbcc4498736580640c6287b57872617a2Adam Lesinski                packageName != String16("android")) {
27406022debdbcc4498736580640c6287b57872617a2Adam Lesinski            libraryPackages.add(sp<Package>(new Package(packageName, packageId)));
27416022debdbcc4498736580640c6287b57872617a2Adam Lesinski        }
27426022debdbcc4498736580640c6287b57872617a2Adam Lesinski    }
2743de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski
2744282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Iterate through all data, collecting all values (strings,
2745282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // references, etc).
2746282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    StringPool valueStrings(useUTF8);
2747282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Vector<sp<Entry> > allEntries;
2748282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (pi=0; pi<N; pi++) {
2749282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Package> p = mOrderedPackages.itemAt(pi);
2750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (p->getTypes().size() == 0) {
2751282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
2752282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2753282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2754282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        StringPool typeStrings(useUTF8);
2755282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        StringPool keyStrings(useUTF8);
2756282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2757833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        ssize_t stringsAdded = 0;
2758282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t N = p->getOrderedTypes().size();
2759282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (size_t ti=0; ti<N; ti++) {
2760282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<Type> t = p->getOrderedTypes().itemAt(ti);
2761282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (t == NULL) {
2762282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                typeStrings.add(String16("<empty>"), false);
2763833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                stringsAdded++;
2764282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
2765282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2766833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski
2767833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            while (stringsAdded < t->getIndex() - 1) {
2768833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                typeStrings.add(String16("<empty>"), false);
2769833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                stringsAdded++;
2770833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            }
2771833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski
2772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const String16 typeName(t->getName());
2773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            typeStrings.add(typeName, false);
2774833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            stringsAdded++;
2775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2776282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // This is a hack to tweak the sorting order of the final strings,
2777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // to put stuff that is generally not language-specific first.
2778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 configTypeName(typeName);
2779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (configTypeName == "drawable" || configTypeName == "layout"
2780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    || configTypeName == "color" || configTypeName == "anim"
2781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    || configTypeName == "interpolator" || configTypeName == "animator"
2782282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    || configTypeName == "xml" || configTypeName == "menu"
2783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    || configTypeName == "mipmap" || configTypeName == "raw") {
2784282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                configTypeName = "1complex";
2785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
2786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                configTypeName = "2value";
2787282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2788282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
278927f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski            // mipmaps don't get filtered, so they will
279027f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski            // allways end up in the base. Make sure they
279127f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski            // don't end up in a split.
279227f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski            if (typeName == mipmap16 && !isBase) {
279327f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski                continue;
279427f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski            }
279527f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski
2796282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const bool filterable = (typeName != mipmap16);
2797282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2798282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t N = t->getOrderedConfigs().size();
2799282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t ci=0; ci<N; ci++) {
2800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<ConfigList> c = t->getOrderedConfigs().itemAt(ci);
2801282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (c == NULL) {
2802282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
2803282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2804282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                const size_t N = c->getEntries().size();
2805282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                for (size_t ei=0; ei<N; ei++) {
2806282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    ConfigDescription config = c->getEntries().keyAt(ei);
2807fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    if (filterable && !filter->match(config)) {
2808282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        continue;
2809282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2810282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sp<Entry> e = c->getEntries().valueAt(ei);
2811282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (e == NULL) {
2812282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        continue;
2813282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    e->setNameIndex(keyStrings.add(e->getName(), true));
2815282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2816282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // If this entry has no values for other configs,
2817282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // and is the default config, then it is special.  Otherwise
2818282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // we want to add it with the config info.
2819282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    ConfigDescription* valueConfig = NULL;
2820282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (N != 1 || config == nullConfig) {
2821282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        valueConfig = &config;
2822282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2823282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2824282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    status_t err = e->prepareFlatten(&valueStrings, this,
2825282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            &configTypeName, &config);
2826282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (err != NO_ERROR) {
2827282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        return err;
2828282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2829282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    allEntries.add(e);
2830282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2831282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2832282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2833282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2834282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        p->setTypeStrings(typeStrings.createStringBlock());
2835282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        p->setKeyStrings(keyStrings.createStringBlock());
2836282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2837282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2838282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getOutputAPKFile() != NULL) {
2839282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Now we want to sort the value strings for better locality.  This will
2840282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // cause the positions of the strings to change, so we need to go back
2841282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // through out resource entries and update them accordingly.  Only need
2842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // to do this if actually writing the output file.
2843282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        valueStrings.sortByConfig();
2844282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (pi=0; pi<allEntries.size(); pi++) {
2845282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            allEntries[pi]->remapStringValue(&valueStrings);
2846282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2847282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2848282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2849282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t strAmt = 0;
2850de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski
2851282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Now build the array of package chunks.
2852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Vector<sp<AaptFile> > flatPackages;
2853282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (pi=0; pi<N; pi++) {
2854282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Package> p = mOrderedPackages.itemAt(pi);
2855282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (p->getTypes().size() == 0) {
2856282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Empty, skip!
2857282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
2858282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2859282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2860282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t N = p->getTypeStrings().size();
2861282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2862282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t baseSize = sizeof(ResTable_package);
2863282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2864282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Start the package data.
2865282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<AaptFile> data = new AaptFile(String8(), AaptGroupEntry(), String8());
2866282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ResTable_package* header = (ResTable_package*)data->editData(baseSize);
2867282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (header == NULL) {
2868282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: out of memory creating ResTable_package\n");
2869282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return NO_MEMORY;
2870282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2871282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        memset(header, 0, sizeof(*header));
2872282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header->header.type = htods(RES_TABLE_PACKAGE_TYPE);
2873282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header->header.headerSize = htods(sizeof(*header));
2874833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        header->id = htodl(static_cast<uint32_t>(p->getAssignedId()));
2875282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        strcpy16_htod(header->name, p->getName().string());
2876282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2877282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Write the string blocks.
2878282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t typeStringsStart = data->getSize();
2879282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<AaptFile> strFile = p->getTypeStringsData();
2880282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ssize_t amt = data->writeData(strFile->getData(), strFile->getSize());
2881282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        #if PRINT_STRING_METRICS
2882282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "**** type strings: %d\n", amt);
2883282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        #endif
2884282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        strAmt += amt;
2885282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (amt < 0) {
2886282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return amt;
2887282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2888282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t keyStringsStart = data->getSize();
2889282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        strFile = p->getKeyStringsData();
2890282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        amt = data->writeData(strFile->getData(), strFile->getSize());
2891282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        #if PRINT_STRING_METRICS
2892282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "**** key strings: %d\n", amt);
2893282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        #endif
2894282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        strAmt += amt;
2895282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (amt < 0) {
2896282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return amt;
2897282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2898282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
289927f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski        if (isBase) {
290027f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski            status_t err = flattenLibraryTable(data, libraryPackages);
290127f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski            if (err != NO_ERROR) {
290227f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski                fprintf(stderr, "ERROR: failed to write library table\n");
290327f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski                return err;
290427f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski            }
2905de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski        }
2906de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski
2907282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Build the type chunks inside of this package.
2908282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (size_t ti=0; ti<N; ti++) {
2909282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Retrieve them in the same order as the type string block.
2910282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            size_t len;
2911282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String16 typeName(p->getTypeStrings().stringAt(ti, &len));
2912282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<Type> t = p->getTypes().valueFor(typeName);
2913282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            LOG_ALWAYS_FATAL_IF(t == NULL && typeName != String16("<empty>"),
2914282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                "Type name %s not found",
2915282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                String8(typeName).string());
2916833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            if (t == NULL) {
2917833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                continue;
2918833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            }
2919282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const bool filterable = (typeName != mipmap16);
292027f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski            const bool skipEntireType = (typeName == mipmap16 && !isBase);
2921282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2922282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t N = t != NULL ? t->getOrderedConfigs().size() : 0;
2923282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2924282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Until a non-NO_ENTRY value has been written for a resource,
2925282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // that resource is invalid; validResources[i] represents
2926282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // the item at t->getOrderedConfigs().itemAt(i).
2927282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Vector<bool> validResources;
2928282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            validResources.insertAt(false, 0, N);
2929282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2930282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // First write the typeSpec chunk, containing information about
2931282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // each resource entry in this type.
2932282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            {
2933282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                const size_t typeSpecSize = sizeof(ResTable_typeSpec) + sizeof(uint32_t)*N;
2934282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                const size_t typeSpecStart = data->getSize();
2935282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ResTable_typeSpec* tsHeader = (ResTable_typeSpec*)
2936282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    (((uint8_t*)data->editData(typeSpecStart+typeSpecSize)) + typeSpecStart);
2937282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (tsHeader == NULL) {
2938282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    fprintf(stderr, "ERROR: out of memory creating ResTable_typeSpec\n");
2939282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return NO_MEMORY;
2940282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2941282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                memset(tsHeader, 0, sizeof(*tsHeader));
2942282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tsHeader->header.type = htods(RES_TABLE_TYPE_SPEC_TYPE);
2943282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tsHeader->header.headerSize = htods(sizeof(*tsHeader));
2944282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tsHeader->header.size = htodl(typeSpecSize);
2945282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tsHeader->id = ti+1;
2946282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tsHeader->entryCount = htodl(N);
2947282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2948282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                uint32_t* typeSpecFlags = (uint32_t*)
2949282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    (((uint8_t*)data->editData())
2950282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        + typeSpecStart + sizeof(ResTable_typeSpec));
2951282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                memset(typeSpecFlags, 0, sizeof(uint32_t)*N);
2952282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2953282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                for (size_t ei=0; ei<N; ei++) {
2954282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sp<ConfigList> cl = t->getOrderedConfigs().itemAt(ei);
2955282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (cl->getPublic()) {
2956282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        typeSpecFlags[ei] |= htodl(ResTable_typeSpec::SPEC_PUBLIC);
2957282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
295827f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski
295927f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski                    if (skipEntireType) {
296027f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski                        continue;
296127f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski                    }
296227f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski
2963282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    const size_t CN = cl->getEntries().size();
2964282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    for (size_t ci=0; ci<CN; ci++) {
2965fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                        if (filterable && !filter->match(cl->getEntries().keyAt(ci))) {
2966282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            continue;
2967282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
2968282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        for (size_t cj=ci+1; cj<CN; cj++) {
2969fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                            if (filterable && !filter->match(cl->getEntries().keyAt(cj))) {
2970282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                continue;
2971282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
2972282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            typeSpecFlags[ei] |= htodl(
2973282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                cl->getEntries().keyAt(ci).diff(cl->getEntries().keyAt(cj)));
2974282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
2975282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2976282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2977282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2978282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
297927f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski            if (skipEntireType) {
298027f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski                continue;
298127f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski            }
298227f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski
2983282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // We need to write one type chunk for each configuration for
2984282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // which we have entries in this type.
2985282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t NC = t->getUniqueConfigs().size();
2986282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2987282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t typeSize = sizeof(ResTable_type) + sizeof(uint32_t)*N;
2988282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2989282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t ci=0; ci<NC; ci++) {
2990282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ConfigDescription config = t->getUniqueConfigs().itemAt(ci);
2991282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2992282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                NOISY(printf("Writing config %d config: imsi:%d/%d lang:%c%c cnt:%c%c "
2993282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                     "orien:%d ui:%d touch:%d density:%d key:%d inp:%d nav:%d sz:%dx%d "
2994282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                     "sw%ddp w%ddp h%ddp dir:%d\n",
2995282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      ti+1,
2996282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.mcc, config.mnc,
2997282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.language[0] ? config.language[0] : '-',
2998282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.language[1] ? config.language[1] : '-',
2999282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.country[0] ? config.country[0] : '-',
3000282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.country[1] ? config.country[1] : '-',
3001282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.orientation,
3002282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.uiMode,
3003282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.touchscreen,
3004282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.density,
3005282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.keyboard,
3006282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.inputFlags,
3007282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.navigation,
3008282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.screenWidth,
3009282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.screenHeight,
3010282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.smallestScreenWidthDp,
3011282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.screenWidthDp,
3012282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.screenHeightDp,
3013282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.layoutDirection));
3014282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3015fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                if (filterable && !filter->match(config)) {
3016282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
3017282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3018282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3019282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                const size_t typeStart = data->getSize();
3020282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3021282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ResTable_type* tHeader = (ResTable_type*)
3022282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    (((uint8_t*)data->editData(typeStart+typeSize)) + typeStart);
3023282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (tHeader == NULL) {
3024282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    fprintf(stderr, "ERROR: out of memory creating ResTable_type\n");
3025282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return NO_MEMORY;
3026282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3027282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3028282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                memset(tHeader, 0, sizeof(*tHeader));
3029282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tHeader->header.type = htods(RES_TABLE_TYPE_TYPE);
3030282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tHeader->header.headerSize = htods(sizeof(*tHeader));
3031282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tHeader->id = ti+1;
3032282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tHeader->entryCount = htodl(N);
3033282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tHeader->entriesStart = htodl(typeSize);
3034282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tHeader->config = config;
3035282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                NOISY(printf("Writing type %d config: imsi:%d/%d lang:%c%c cnt:%c%c "
3036282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                     "orien:%d ui:%d touch:%d density:%d key:%d inp:%d nav:%d sz:%dx%d "
3037282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                     "sw%ddp w%ddp h%ddp dir:%d\n",
3038282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      ti+1,
3039282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.mcc, tHeader->config.mnc,
3040282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.language[0] ? tHeader->config.language[0] : '-',
3041282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.language[1] ? tHeader->config.language[1] : '-',
3042282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.country[0] ? tHeader->config.country[0] : '-',
3043282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.country[1] ? tHeader->config.country[1] : '-',
3044282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.orientation,
3045282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.uiMode,
3046282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.touchscreen,
3047282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.density,
3048282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.keyboard,
3049282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.inputFlags,
3050282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.navigation,
3051282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.screenWidth,
3052282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.screenHeight,
3053282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.smallestScreenWidthDp,
3054282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.screenWidthDp,
3055282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.screenHeightDp,
3056282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.layoutDirection));
3057282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tHeader->config.swapHtoD();
3058282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3059282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Build the entries inside of this type.
3060282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                for (size_t ei=0; ei<N; ei++) {
3061282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sp<ConfigList> cl = t->getOrderedConfigs().itemAt(ei);
3062282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sp<Entry> e = cl->getEntries().valueFor(config);
3063282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3064282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // Set the offset for this entry in its type.
3065282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    uint32_t* index = (uint32_t*)
3066282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        (((uint8_t*)data->editData())
3067282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            + typeStart + sizeof(ResTable_type));
3068282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (e != NULL) {
3069282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        index[ei] = htodl(data->getSize()-typeStart-typeSize);
3070282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3071282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        // Create the entry.
3072282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ssize_t amt = e->flatten(bundle, data, cl->getPublic());
3073282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (amt < 0) {
3074282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            return amt;
3075282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
3076282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        validResources.editItemAt(ei) = true;
3077282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else {
3078282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        index[ei] = htodl(ResTable_type::NO_ENTRY);
3079282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
3080282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3081282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3082282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Fill in the rest of the type information.
3083282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tHeader = (ResTable_type*)
3084282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    (((uint8_t*)data->editData()) + typeStart);
3085282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tHeader->header.size = htodl(data->getSize()-typeStart);
3086282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3087282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3088833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            // If we're building splits, then each invocation of the flattening
3089833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            // step will have 'missing' entries. Don't warn/error for this case.
3090833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            if (bundle->getSplitConfigurations().isEmpty()) {
3091833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                bool missing_entry = false;
3092833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                const char* log_prefix = bundle->getErrorOnMissingConfigEntry() ?
3093833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                        "error" : "warning";
3094833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                for (size_t i = 0; i < N; ++i) {
3095833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                    if (!validResources[i]) {
3096833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                        sp<ConfigList> c = t->getOrderedConfigs().itemAt(i);
3097833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                        fprintf(stderr, "%s: no entries written for %s/%s (0x%08x)\n", log_prefix,
3098833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                                String8(typeName).string(), String8(c->getName()).string(),
3099833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                                Res_MAKEID(p->getAssignedId() - 1, ti, i));
3100833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                        missing_entry = true;
3101833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                    }
3102833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                }
3103833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                if (bundle->getErrorOnMissingConfigEntry() && missing_entry) {
3104833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                    fprintf(stderr, "Error: Missing entries, quit!\n");
3105833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                    return NOT_ENOUGH_DATA;
3106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3107cd28bd37ea2d88dd72930f032ca73daaad5744b4Ying Wang            }
3108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Fill in the rest of the package information.
3111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header = (ResTable_package*)data->editData();
3112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header->header.size = htodl(data->getSize());
3113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header->typeStrings = htodl(typeStringsStart);
3114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header->lastPublicType = htodl(p->getTypeStrings().size());
3115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header->keyStrings = htodl(keyStringsStart);
3116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header->lastPublicKey = htodl(p->getKeyStrings().size());
3117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        flatPackages.add(data);
3119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // And now write out the final chunks.
3122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t dataStart = dest->getSize();
3123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    {
3125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // blah
3126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ResTable_header header;
3127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        memset(&header, 0, sizeof(header));
3128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header.header.type = htods(RES_TABLE_TYPE);
3129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header.header.headerSize = htods(sizeof(header));
3130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header.packageCount = htodl(flatPackages.size());
3131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        status_t err = dest->writeData(&header, sizeof(header));
3132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != NO_ERROR) {
3133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: out of memory creating ResTable_header\n");
3134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return err;
3135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t strStart = dest->getSize();
3139fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    status_t err = valueStrings.writeStringBlock(dest);
3140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
3141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return err;
3142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t amt = (dest->getSize()-strStart);
3145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    strAmt += amt;
3146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    #if PRINT_STRING_METRICS
3147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(stderr, "**** value strings: %d\n", amt);
3148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(stderr, "**** total strings: %d\n", strAmt);
3149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    #endif
3150de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski
3151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (pi=0; pi<flatPackages.size(); pi++) {
3152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        err = dest->writeData(flatPackages[pi]->getData(),
3153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                              flatPackages[pi]->getSize());
3154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != NO_ERROR) {
3155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: out of memory creating package chunk for ResTable_header\n");
3156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return err;
3157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ResTable_header* header = (ResTable_header*)
3161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        (((uint8_t*)dest->getData()) + dataStart);
3162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    header->header.size = htodl(dest->getSize() - dataStart);
3163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    NOISY(aout << "Resource table:"
3165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski          << HexDump(dest->getData(), dest->getSize()) << endl);
3166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    #if PRINT_STRING_METRICS
3168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(stderr, "**** total resource table size: %d / %d%% strings\n",
3169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest->getSize(), (strAmt*100)/dest->getSize());
3170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    #endif
3171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
3173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3175de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinskistatus_t ResourceTable::flattenLibraryTable(const sp<AaptFile>& dest, const Vector<sp<Package> >& libs) {
3176de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski    // Write out the library table if necessary
3177de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski    if (libs.size() > 0) {
3178de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski        NOISY(fprintf(stderr, "Writing library reference table\n"));
3179de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski
3180de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski        const size_t libStart = dest->getSize();
3181de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski        const size_t count = libs.size();
31826022debdbcc4498736580640c6287b57872617a2Adam Lesinski        ResTable_lib_header* libHeader = (ResTable_lib_header*) dest->editDataInRange(
31836022debdbcc4498736580640c6287b57872617a2Adam Lesinski                libStart, sizeof(ResTable_lib_header));
3184de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski
3185de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski        memset(libHeader, 0, sizeof(*libHeader));
3186de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski        libHeader->header.type = htods(RES_TABLE_LIBRARY_TYPE);
3187de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski        libHeader->header.headerSize = htods(sizeof(*libHeader));
3188de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski        libHeader->header.size = htodl(sizeof(*libHeader) + (sizeof(ResTable_lib_entry) * count));
3189de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski        libHeader->count = htodl(count);
3190de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski
3191de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski        // Write the library entries
3192de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski        for (size_t i = 0; i < count; i++) {
3193de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski            const size_t entryStart = dest->getSize();
3194de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski            sp<Package> libPackage = libs[i];
3195de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski            NOISY(fprintf(stderr, "  Entry %s -> 0x%02x\n",
3196de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski                        String8(libPackage->getName()).string(),
3197de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski                        (uint8_t)libPackage->getAssignedId()));
3198de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski
31996022debdbcc4498736580640c6287b57872617a2Adam Lesinski            ResTable_lib_entry* entry = (ResTable_lib_entry*) dest->editDataInRange(
32006022debdbcc4498736580640c6287b57872617a2Adam Lesinski                    entryStart, sizeof(ResTable_lib_entry));
3201de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski            memset(entry, 0, sizeof(*entry));
3202de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski            entry->packageId = htodl(libPackage->getAssignedId());
3203de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski            strcpy16_htod(entry->packageName, libPackage->getName().string());
3204de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski        }
3205de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski    }
3206de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski    return NO_ERROR;
3207de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski}
3208de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski
3209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid ResourceTable::writePublicDefinitions(const String16& package, FILE* fp)
3210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(fp,
3212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    "<!-- This file contains <public> resource definitions for all\n"
3213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    "     resources that were generated from the source data. -->\n"
3214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    "\n"
3215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    "<resources>\n");
3216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    writePublicDefinitions(package, fp, true);
3218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    writePublicDefinitions(package, fp, false);
3219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(fp,
3221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    "\n"
3222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    "</resources>\n");
3223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid ResourceTable::writePublicDefinitions(const String16& package, FILE* fp, bool pub)
3226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool didHeader = false;
3228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Package> pkg = mPackages.valueFor(package);
3230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (pkg != NULL) {
3231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t NT = pkg->getOrderedTypes().size();
3232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (size_t i=0; i<NT; i++) {
3233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<Type> t = pkg->getOrderedTypes().itemAt(i);
3234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (t == NULL) {
3235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
3236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool didType = false;
3239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t NC = t->getOrderedConfigs().size();
3241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t j=0; j<NC; j++) {
3242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<ConfigList> c = t->getOrderedConfigs().itemAt(j);
3243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (c == NULL) {
3244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
3245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (c->getPublic() != pub) {
3248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
3249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!didType) {
3252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    fprintf(fp, "\n");
3253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    didType = true;
3254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!didHeader) {
3256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (pub) {
3257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        fprintf(fp,"  <!-- PUBLIC SECTION.  These resources have been declared public.\n");
3258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        fprintf(fp,"       Changes to these definitions will break binary compatibility. -->\n\n");
3259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else {
3260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        fprintf(fp,"  <!-- PRIVATE SECTION.  These resources have not been declared public.\n");
3261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        fprintf(fp,"       You can make them public my moving these lines into a file in res/values. -->\n\n");
3262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
3263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    didHeader = true;
3264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!pub) {
3266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    const size_t NE = c->getEntries().size();
3267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    for (size_t k=0; k<NE; k++) {
3268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const SourcePos& pos = c->getEntries().valueAt(k)->getPos();
3269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (pos.file != "") {
3270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            fprintf(fp,"  <!-- Declared at %s:%d -->\n",
3271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    pos.file.string(), pos.line);
3272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
3273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
3274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(fp, "  <public type=\"%s\" name=\"%s\" id=\"0x%08x\" />\n",
3276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8(t->getName()).string(),
3277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8(c->getName()).string(),
3278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        getResId(pkg, t, c->getEntryIndex()));
3279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3284282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiResourceTable::Item::Item(const SourcePos& _sourcePos,
3285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                          bool _isId,
3286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                          const String16& _value,
3287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                          const Vector<StringPool::entry_style_span>* _style,
3288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                          int32_t _format)
3289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    : sourcePos(_sourcePos)
3290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    , isId(_isId)
3291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    , value(_value)
3292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    , format(_format)
3293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    , bagKeyId(0)
3294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    , evaluating(false)
3295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (_style) {
3297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        style = *_style;
3298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
330182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam LesinskiResourceTable::Entry::Entry(const Entry& entry)
330282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    : RefBase()
330382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    , mName(entry.mName)
330482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    , mParent(entry.mParent)
330582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    , mType(entry.mType)
330682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    , mItem(entry.mItem)
330782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    , mItemFormat(entry.mItemFormat)
330882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    , mBag(entry.mBag)
330982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    , mNameIndex(entry.mNameIndex)
331082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    , mParentId(entry.mParentId)
331182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    , mPos(entry.mPos) {}
331282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski
3313978ab9d92934b79409638cf220de3002fea8d505Adam LesinskiResourceTable::Entry& ResourceTable::Entry::operator=(const Entry& entry) {
3314978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski    mName = entry.mName;
3315978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski    mParent = entry.mParent;
3316978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski    mType = entry.mType;
3317978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski    mItem = entry.mItem;
3318978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski    mItemFormat = entry.mItemFormat;
3319978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski    mBag = entry.mBag;
3320978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski    mNameIndex = entry.mNameIndex;
3321978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski    mParentId = entry.mParentId;
3322978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski    mPos = entry.mPos;
3323978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski    return *this;
3324978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski}
3325978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski
3326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Entry::makeItABag(const SourcePos& sourcePos)
3327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mType == TYPE_BAG) {
3329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NO_ERROR;
3330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mType == TYPE_UNKNOWN) {
3332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mType = TYPE_BAG;
3333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NO_ERROR;
3334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sourcePos.error("Resource entry %s is already defined as a single item.\n"
3336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    "%s:%d: Originally defined here.\n",
3337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(mName).string(),
3338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    mItem.sourcePos.file.string(), mItem.sourcePos.line);
3339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return UNKNOWN_ERROR;
3340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Entry::setItem(const SourcePos& sourcePos,
3343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       const String16& value,
3344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       const Vector<StringPool::entry_style_span>* style,
3345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       int32_t format,
3346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       const bool overwrite)
3347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Item item(sourcePos, false, value, style);
3349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mType == TYPE_BAG) {
335143a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski        if (mBag.size() == 0) {
335243a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski            sourcePos.error("Resource entry %s is already defined as a bag.",
335343a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski                    String8(mName).string());
335443a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski        } else {
335543a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski            const Item& item(mBag.valueAt(0));
335643a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski            sourcePos.error("Resource entry %s is already defined as a bag.\n"
335743a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski                            "%s:%d: Originally defined here.\n",
335843a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski                            String8(mName).string(),
335943a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski                            item.sourcePos.file.string(), item.sourcePos.line);
336043a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski        }
3361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
3362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if ( (mType != TYPE_UNKNOWN) && (overwrite == false) ) {
3364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sourcePos.error("Resource entry %s is already defined.\n"
3365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "%s:%d: Originally defined here.\n",
3366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8(mName).string(),
3367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        mItem.sourcePos.file.string(), mItem.sourcePos.line);
3368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
3369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mType = TYPE_ITEM;
3372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mItem = item;
3373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mItemFormat = format;
3374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
3375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Entry::addToBag(const SourcePos& sourcePos,
3378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        const String16& key, const String16& value,
3379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        const Vector<StringPool::entry_style_span>* style,
3380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        bool replace, bool isId, int32_t format)
3381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = makeItABag(sourcePos);
3383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
3384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return err;
3385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Item item(sourcePos, isId, value, style, format);
3388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // XXX NOTE: there is an error if you try to have a bag with two keys,
3390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // one an attr and one an id, with the same name.  Not something we
3391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // currently ever have to worry about.
3392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t origKey = mBag.indexOfKey(key);
3393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (origKey >= 0) {
3394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!replace) {
3395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const Item& item(mBag.valueAt(origKey));
3396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sourcePos.error("Resource entry %s already has bag item %s.\n"
3397282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    "%s:%d: Originally defined here.\n",
3398282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(mName).string(), String8(key).string(),
3399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    item.sourcePos.file.string(), item.sourcePos.line);
3400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return UNKNOWN_ERROR;
3401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //printf("Replacing %s with %s\n",
3403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //       String8(mBag.valueFor(key).value).string(), String8(value).string());
3404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mBag.replaceValueFor(key, item);
3405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mBag.add(key, item);
3408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
3409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
341182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinskistatus_t ResourceTable::Entry::removeFromBag(const String16& key) {
341282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    if (mType != Entry::TYPE_BAG) {
341382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski        return NO_ERROR;
341482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    }
341582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski
341682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    if (mBag.removeItem(key) >= 0) {
341782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski        return NO_ERROR;
341882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    }
341982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    return UNKNOWN_ERROR;
342082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski}
342182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski
3422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Entry::emptyBag(const SourcePos& sourcePos)
3423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = makeItABag(sourcePos);
3425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
3426282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return err;
3427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mBag.clear();
3430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
3431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Entry::generateAttributes(ResourceTable* table,
3434282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                  const String16& package)
3435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 attr16("attr");
3437282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 id16("id");
3438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t N = mBag.size();
3439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (size_t i=0; i<N; i++) {
3440282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String16& key = mBag.keyAt(i);
3441282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const Item& it = mBag.valueAt(i);
3442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (it.isId) {
3443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!table->hasBagOrEntry(key, &id16, &package)) {
3444282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 value("false");
344543a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski                NOISY(fprintf(stderr, "Generating %s:id/%s\n",
344643a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski                        String8(package).string(),
344743a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski                        String8(key).string()));
3448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                status_t err = table->addEntry(SourcePos(String8("<generated>"), 0), package,
3449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                               id16, key, value);
3450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (err != NO_ERROR) {
3451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return err;
3452282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else if (!table->hasBagOrEntry(key, &attr16, &package)) {
3455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#if 1
3457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//             fprintf(stderr, "ERROR: Bag attribute '%s' has not been defined.\n",
3458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//                     String8(key).string());
3459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//             const Item& item(mBag.valueAt(i));
3460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//             fprintf(stderr, "Referenced from file %s line %d\n",
3461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//                     item.sourcePos.file.string(), item.sourcePos.line);
3462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//             return UNKNOWN_ERROR;
3463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#else
3464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            char numberStr[16];
3465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sprintf(numberStr, "%d", ResTable_map::TYPE_ANY);
3466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            status_t err = table->addBag(SourcePos("<generated>", 0), package,
3467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                         attr16, key, String16(""),
3468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                         String16("^type"),
3469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                         String16(numberStr), NULL, NULL);
3470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (err != NO_ERROR) {
3471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return err;
3472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif
3474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
3477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3479282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Entry::assignResourceIds(ResourceTable* table,
3480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                 const String16& package)
3481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool hasErrors = false;
3483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mType == TYPE_BAG) {
3485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const char* errorMsg;
3486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String16 style16("style");
3487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String16 attr16("attr");
3488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String16 id16("id");
3489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mParentId = 0;
3490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (mParent.size() > 0) {
3491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mParentId = table->getResId(mParent, &style16, NULL, &errorMsg);
3492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (mParentId == 0) {
3493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                mPos.error("Error retrieving parent for item: %s '%s'.\n",
3494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        errorMsg, String8(mParent).string());
3495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                hasErrors = true;
3496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t N = mBag.size();
3499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (size_t i=0; i<N; i++) {
3500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const String16& key = mBag.keyAt(i);
3501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Item& it = mBag.editValueAt(i);
3502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            it.bagKeyId = table->getResId(key,
3503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    it.isId ? &id16 : &attr16, NULL, &errorMsg);
3504282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //printf("Bag key of %s: #%08x\n", String8(key).string(), it.bagKeyId);
3505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (it.bagKeyId == 0) {
3506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                it.sourcePos.error("Error: %s: %s '%s'.\n", errorMsg,
3507282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8(it.isId ? id16 : attr16).string(),
3508282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8(key).string());
3509282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                hasErrors = true;
3510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3511282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3512282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3513282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return hasErrors ? UNKNOWN_ERROR : NO_ERROR;
3514282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3515282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3516282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Entry::prepareFlatten(StringPool* strings, ResourceTable* table,
3517282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String8* configTypeName, const ConfigDescription* config)
3518282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3519282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mType == TYPE_ITEM) {
3520282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Item& it = mItem;
3521282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        AccessorCookie ac(it.sourcePos, String8(mName), String8(it.value));
3522282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!table->stringToValue(&it.parsedValue, strings,
3523282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  it.value, false, true, 0,
3524282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  &it.style, NULL, &ac, mItemFormat,
3525282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  configTypeName, config)) {
3526282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return UNKNOWN_ERROR;
3527282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3528282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else if (mType == TYPE_BAG) {
3529282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t N = mBag.size();
3530282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (size_t i=0; i<N; i++) {
3531282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const String16& key = mBag.keyAt(i);
3532282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Item& it = mBag.editValueAt(i);
3533282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            AccessorCookie ac(it.sourcePos, String8(key), String8(it.value));
3534282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!table->stringToValue(&it.parsedValue, strings,
3535282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                      it.value, false, true, it.bagKeyId,
3536282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                      &it.style, NULL, &ac, it.format,
3537282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                      configTypeName, config)) {
3538282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return UNKNOWN_ERROR;
3539282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3540282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3541282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
3542282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mPos.error("Error: entry %s is not a single item or a bag.\n",
3543282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                   String8(mName).string());
3544282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
3545282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3546282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
3547282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3548282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3549282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Entry::remapStringValue(StringPool* strings)
3550282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3551282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mType == TYPE_ITEM) {
3552282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Item& it = mItem;
3553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (it.parsedValue.dataType == Res_value::TYPE_STRING) {
3554282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            it.parsedValue.data = strings->mapOriginalPosToNewPos(it.parsedValue.data);
3555282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3556282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else if (mType == TYPE_BAG) {
3557282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t N = mBag.size();
3558282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (size_t i=0; i<N; i++) {
3559282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Item& it = mBag.editValueAt(i);
3560282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (it.parsedValue.dataType == Res_value::TYPE_STRING) {
3561282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                it.parsedValue.data = strings->mapOriginalPosToNewPos(it.parsedValue.data);
3562282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3563282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3564282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
3565282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mPos.error("Error: entry %s is not a single item or a bag.\n",
3566282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                   String8(mName).string());
3567282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
3568282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3569282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
3570282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3571282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskissize_t ResourceTable::Entry::flatten(Bundle* bundle, const sp<AaptFile>& data, bool isPublic)
3573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t amt = 0;
3575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ResTable_entry header;
3576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    memset(&header, 0, sizeof(header));
3577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    header.size = htods(sizeof(header));
3578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const type ty = this != NULL ? mType : TYPE_ITEM;
3579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (this != NULL) {
3580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (ty == TYPE_BAG) {
3581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            header.flags |= htods(header.FLAG_COMPLEX);
3582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (isPublic) {
3584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            header.flags |= htods(header.FLAG_PUBLIC);
3585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header.key.index = htodl(mNameIndex);
3587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (ty != TYPE_BAG) {
3589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        status_t err = data->writeData(&header, sizeof(header));
3590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != NO_ERROR) {
3591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: out of memory creating ResTable_entry\n");
3592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return err;
3593282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const Item& it = mItem;
3596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Res_value par;
3597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        memset(&par, 0, sizeof(par));
3598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        par.size = htods(it.parsedValue.size);
3599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        par.dataType = it.parsedValue.dataType;
3600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        par.res0 = it.parsedValue.res0;
3601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        par.data = htodl(it.parsedValue.data);
3602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        #if 0
3603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printf("Writing item (%s): type=%d, data=0x%x, res0=0x%x\n",
3604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski               String8(mName).string(), it.parsedValue.dataType,
3605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski               it.parsedValue.data, par.res0);
3606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        #endif
3607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        err = data->writeData(&par, it.parsedValue.size);
3608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != NO_ERROR) {
3609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: out of memory creating Res_value\n");
3610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return err;
3611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        amt += it.parsedValue.size;
3613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
3614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        size_t N = mBag.size();
3615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        size_t i;
3616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Create correct ordering of items.
3617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        KeyedVector<uint32_t, const Item*> items;
3618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (i=0; i<N; i++) {
3619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const Item& it = mBag.valueAt(i);
3620282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            items.add(it.bagKeyId, &it);
3621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        N = items.size();
3623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ResTable_map_entry mapHeader;
3625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        memcpy(&mapHeader, &header, sizeof(header));
3626282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mapHeader.size = htods(sizeof(mapHeader));
3627282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mapHeader.parent.ident = htodl(mParentId);
3628282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mapHeader.count = htodl(N);
3629282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        status_t err = data->writeData(&mapHeader, sizeof(mapHeader));
3630282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != NO_ERROR) {
3631282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: out of memory creating ResTable_entry\n");
3632282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return err;
3633282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3634282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (i=0; i<N; i++) {
3636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const Item& it = *items.valueAt(i);
3637282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ResTable_map map;
3638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            map.name.ident = htodl(it.bagKeyId);
3639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            map.value.size = htods(it.parsedValue.size);
3640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            map.value.dataType = it.parsedValue.dataType;
3641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            map.value.res0 = it.parsedValue.res0;
3642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            map.value.data = htodl(it.parsedValue.data);
3643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            err = data->writeData(&map, sizeof(map));
3644282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (err != NO_ERROR) {
3645282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, "ERROR: out of memory creating Res_value\n");
3646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return err;
3647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3648282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            amt += sizeof(map);
3649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return amt;
3652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid ResourceTable::ConfigList::appendComment(const String16& comment,
3655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                              bool onlyIfEmpty)
3656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (comment.size() <= 0) {
3658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return;
3659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (onlyIfEmpty && mComment.size() > 0) {
3661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return;
3662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mComment.size() > 0) {
3664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mComment.append(String16("\n"));
3665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mComment.append(comment);
3667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid ResourceTable::ConfigList::appendTypeComment(const String16& comment)
3670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (comment.size() <= 0) {
3672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return;
3673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mTypeComment.size() > 0) {
3675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mTypeComment.append(String16("\n"));
3676282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3677282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mTypeComment.append(comment);
3678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3679282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3680282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Type::addPublic(const SourcePos& sourcePos,
3681282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        const String16& name,
3682282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        const uint32_t ident)
3683282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3684282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    #if 0
3685282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int32_t entryIdx = Res_GETENTRY(ident);
3686282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (entryIdx < 0) {
3687282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sourcePos.error("Public resource %s/%s has an invalid 0 identifier (0x%08x).\n",
3688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String8(mName).string(), String8(name).string(), ident);
3689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
3690282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3691282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    #endif
3692282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3693282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int32_t typeIdx = Res_GETTYPE(ident);
3694282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (typeIdx >= 0) {
3695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        typeIdx++;
3696282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (mPublicIndex > 0 && mPublicIndex != typeIdx) {
3697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sourcePos.error("Public resource %s/%s has conflicting type codes for its"
3698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    " public identifiers (0x%x vs 0x%x).\n",
3699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(mName).string(), String8(name).string(),
3700282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    mPublicIndex, typeIdx);
3701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return UNKNOWN_ERROR;
3702282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3703282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mPublicIndex = typeIdx;
3704282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3705282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3706282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mFirstPublicSourcePos == NULL) {
3707282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mFirstPublicSourcePos = new SourcePos(sourcePos);
3708282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3709282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3710282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mPublic.indexOfKey(name) < 0) {
3711282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mPublic.add(name, Public(sourcePos, String16(), ident));
3712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
3713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Public& p = mPublic.editValueFor(name);
3714282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (p.ident != ident) {
3715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sourcePos.error("Public resource %s/%s has conflicting public identifiers"
3716282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    " (0x%08x vs 0x%08x).\n"
3717282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    "%s:%d: Originally defined here.\n",
3718282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(mName).string(), String8(name).string(), p.ident, ident,
3719282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    p.sourcePos.file.string(), p.sourcePos.line);
3720282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return UNKNOWN_ERROR;
3721282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3722282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3723282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3724282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
3725282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3726282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3727282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid ResourceTable::Type::canAddEntry(const String16& name)
3728282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3729282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mCanAddEntries.add(name);
3730282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3731282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3732282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisp<ResourceTable::Entry> ResourceTable::Type::getEntry(const String16& entry,
3733282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                       const SourcePos& sourcePos,
3734282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                       const ResTable_config* config,
3735282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                       bool doSetIndex,
3736282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                       bool overlay,
3737282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                       bool autoAddOverlay)
3738282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3739282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int pos = -1;
3740282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<ConfigList> c = mConfigs.valueFor(entry);
3741282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (c == NULL) {
3742282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (overlay && !autoAddOverlay && mCanAddEntries.indexOf(entry) < 0) {
3743282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sourcePos.error("Resource at %s appears in overlay but not"
3744282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            " in the base package; use <add-resource> to add.\n",
3745282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            String8(entry).string());
3746282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return NULL;
3747282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3748282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        c = new ConfigList(entry, sourcePos);
3749282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mConfigs.add(entry, c);
3750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        pos = (int)mOrderedConfigs.size();
3751282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mOrderedConfigs.add(c);
3752282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (doSetIndex) {
3753282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            c->setEntryIndex(pos);
3754282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3755282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3756282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3757282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ConfigDescription cdesc;
3758282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (config) cdesc = *config;
3759282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3760282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Entry> e = c->getEntries().valueFor(cdesc);
3761282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (e == NULL) {
3762282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (config != NULL) {
3763282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            NOISY(printf("New entry at %s:%d: imsi:%d/%d lang:%c%c cnt:%c%c "
3764282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    "orien:%d touch:%d density:%d key:%d inp:%d nav:%d sz:%dx%d "
3765282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    "sw%ddp w%ddp h%ddp dir:%d\n",
3766282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      sourcePos.file.string(), sourcePos.line,
3767282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->mcc, config->mnc,
3768282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->language[0] ? config->language[0] : '-',
3769282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->language[1] ? config->language[1] : '-',
3770282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->country[0] ? config->country[0] : '-',
3771282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->country[1] ? config->country[1] : '-',
3772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->orientation,
3773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->touchscreen,
3774282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->density,
3775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->keyboard,
3776282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->inputFlags,
3777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->navigation,
3778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->screenWidth,
3779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->screenHeight,
3780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->smallestScreenWidthDp,
3781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->screenWidthDp,
3782282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->screenHeightDp,
3783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->layoutDirection));
3784282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
3785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            NOISY(printf("New entry at %s:%d: NULL config\n",
3786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      sourcePos.file.string(), sourcePos.line));
3787282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3788282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        e = new Entry(entry, sourcePos);
3789282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        c->addEntry(cdesc, e);
3790282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        /*
3791282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (doSetIndex) {
3792282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (pos < 0) {
3793282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                for (pos=0; pos<(int)mOrderedConfigs.size(); pos++) {
3794282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (mOrderedConfigs[pos] == c) {
3795282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        break;
3796282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
3797282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3798282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (pos >= (int)mOrderedConfigs.size()) {
3799282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sourcePos.error("Internal error: config not found in mOrderedConfigs when adding entry");
3800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return NULL;
3801282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3802282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3803282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            e->setEntryIndex(pos);
3804282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3805282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        */
3806282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3807282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3808282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mUniqueConfigs.add(cdesc);
3809282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3810282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return e;
3811282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3812282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3813282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Type::applyPublicEntryOrder()
3814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3815282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t N = mOrderedConfigs.size();
3816282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Vector<sp<ConfigList> > origOrder(mOrderedConfigs);
3817282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool hasError = false;
3818282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3819282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t i;
3820282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (i=0; i<N; i++) {
3821282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mOrderedConfigs.replaceAt(NULL, i);
3822282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3823282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3824282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t NP = mPublic.size();
3825282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //printf("Ordering %d configs from %d public defs\n", N, NP);
3826282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t j;
3827282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (j=0; j<NP; j++) {
3828282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String16& name = mPublic.keyAt(j);
3829282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const Public& p = mPublic.valueAt(j);
3830282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int32_t idx = Res_GETENTRY(p.ident);
3831282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //printf("Looking for entry \"%s\"/\"%s\" (0x%08x) in %d...\n",
3832282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //       String8(mName).string(), String8(name).string(), p.ident, N);
3833282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        bool found = false;
3834282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (i=0; i<N; i++) {
3835282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<ConfigList> e = origOrder.itemAt(i);
3836282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //printf("#%d: \"%s\"\n", i, String8(e->getName()).string());
3837282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (e->getName() == name) {
3838282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (idx >= (int32_t)mOrderedConfigs.size()) {
3839282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    p.sourcePos.error("Public entry identifier 0x%x entry index "
3840282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            "is larger than available symbols (index %d, total symbols %d).\n",
3841282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            p.ident, idx, mOrderedConfigs.size());
3842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasError = true;
3843282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else if (mOrderedConfigs.itemAt(idx) == NULL) {
3844282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    e->setPublic(true);
3845282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    e->setPublicSourcePos(p.sourcePos);
3846282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    mOrderedConfigs.replaceAt(e, idx);
3847282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    origOrder.removeAt(i);
3848282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    N--;
3849282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    found = true;
3850282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    break;
3851282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
3852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sp<ConfigList> oe = mOrderedConfigs.itemAt(idx);
3853282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3854282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    p.sourcePos.error("Multiple entry names declared for public entry"
3855282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            " identifier 0x%x in type %s (%s vs %s).\n"
3856282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            "%s:%d: Originally defined here.",
3857282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            idx+1, String8(mName).string(),
3858282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            String8(oe->getName()).string(),
3859282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            String8(name).string(),
3860282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            oe->getPublicSourcePos().file.string(),
3861282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            oe->getPublicSourcePos().line);
3862282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasError = true;
3863282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3864282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3865282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3866282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3867282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!found) {
3868282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            p.sourcePos.error("Public symbol %s/%s declared here is not defined.",
3869282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(mName).string(), String8(name).string());
3870282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            hasError = true;
3871282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3872282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3873282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3874282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //printf("Copying back in %d non-public configs, have %d\n", N, origOrder.size());
3875282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3876282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (N != origOrder.size()) {
3877282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printf("Internal error: remaining private symbol count mismatch\n");
3878282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        N = origOrder.size();
3879282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3880282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3881282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    j = 0;
3882282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (i=0; i<N; i++) {
3883282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<ConfigList> e = origOrder.itemAt(i);
3884282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // There will always be enough room for the remaining entries.
3885282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        while (mOrderedConfigs.itemAt(j) != NULL) {
3886282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            j++;
3887282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3888282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mOrderedConfigs.replaceAt(e, j);
3889282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        j++;
3890282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3891282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3892282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return hasError ? UNKNOWN_ERROR : NO_ERROR;
3893282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3894282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3895833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam LesinskiResourceTable::Package::Package(const String16& name, size_t packageId)
3896833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    : mName(name), mPackageId(packageId),
3897282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      mTypeStringsMapping(0xffffffff),
3898282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      mKeyStringsMapping(0xffffffff)
3899282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3900282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3901282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3902282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisp<ResourceTable::Type> ResourceTable::Package::getType(const String16& type,
3903282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                        const SourcePos& sourcePos,
3904282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                        bool doSetIndex)
3905282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3906282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Type> t = mTypes.valueFor(type);
3907282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (t == NULL) {
3908282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        t = new Type(type, sourcePos);
3909282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mTypes.add(type, t);
3910282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mOrderedTypes.add(t);
3911282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (doSetIndex) {
3912282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // For some reason the type's index is set to one plus the index
3913282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // in the mOrderedTypes list, rather than just the index.
3914282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            t->setIndex(mOrderedTypes.size());
3915282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3916282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3917282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return t;
3918282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3919282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3920282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Package::setTypeStrings(const sp<AaptFile>& data)
3921282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3922282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = setStrings(data, &mTypeStrings, &mTypeStringsMapping);
3923282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
3924282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: Type string data is corrupt!\n");
392557079519f4610715e4c0668c641575d10f3d4461Adam Lesinski        return err;
3926282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
392757079519f4610715e4c0668c641575d10f3d4461Adam Lesinski
392857079519f4610715e4c0668c641575d10f3d4461Adam Lesinski    // Retain a reference to the new data after we've successfully replaced
392957079519f4610715e4c0668c641575d10f3d4461Adam Lesinski    // all uses of the old reference (in setStrings() ).
393057079519f4610715e4c0668c641575d10f3d4461Adam Lesinski    mTypeStringsData = data;
393157079519f4610715e4c0668c641575d10f3d4461Adam Lesinski    return NO_ERROR;
3932282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3933282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3934282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Package::setKeyStrings(const sp<AaptFile>& data)
3935282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3936282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = setStrings(data, &mKeyStrings, &mKeyStringsMapping);
3937282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
3938282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: Key string data is corrupt!\n");
393957079519f4610715e4c0668c641575d10f3d4461Adam Lesinski        return err;
3940282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
394157079519f4610715e4c0668c641575d10f3d4461Adam Lesinski
394257079519f4610715e4c0668c641575d10f3d4461Adam Lesinski    // Retain a reference to the new data after we've successfully replaced
394357079519f4610715e4c0668c641575d10f3d4461Adam Lesinski    // all uses of the old reference (in setStrings() ).
394457079519f4610715e4c0668c641575d10f3d4461Adam Lesinski    mKeyStringsData = data;
394557079519f4610715e4c0668c641575d10f3d4461Adam Lesinski    return NO_ERROR;
3946282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3947282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3948282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Package::setStrings(const sp<AaptFile>& data,
3949282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                            ResStringPool* strings,
3950282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                            DefaultKeyedVector<String16, uint32_t>* mappings)
3951282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3952282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (data->getData() == NULL) {
3953282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
3954282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3955282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3956282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    NOISY(aout << "Setting restable string pool: "
3957282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski          << HexDump(data->getData(), data->getSize()) << endl);
3958282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3959282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = strings->setTo(data->getData(), data->getSize());
3960282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err == NO_ERROR) {
3961282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t N = strings->size();
3962282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (size_t i=0; i<N; i++) {
3963282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            size_t len;
3964282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mappings->add(String16(strings->stringAt(i, &len)), i);
3965282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3966282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3967282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return err;
3968282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3969282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3970282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Package::applyPublicTypeOrder()
3971282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3972282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t N = mOrderedTypes.size();
3973282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Vector<sp<Type> > origOrder(mOrderedTypes);
3974282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3975282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t i;
3976282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (i=0; i<N; i++) {
3977282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mOrderedTypes.replaceAt(NULL, i);
3978282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3979282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3980282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (i=0; i<N; i++) {
3981282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Type> t = origOrder.itemAt(i);
3982282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int32_t idx = t->getPublicIndex();
3983282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (idx > 0) {
3984282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            idx--;
3985282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            while (idx >= (int32_t)mOrderedTypes.size()) {
3986282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                mOrderedTypes.add();
3987282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3988282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (mOrderedTypes.itemAt(idx) != NULL) {
3989282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<Type> ot = mOrderedTypes.itemAt(idx);
3990282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                t->getFirstPublicSourcePos().error("Multiple type names declared for public type"
3991282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        " identifier 0x%x (%s vs %s).\n"
3992282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "%s:%d: Originally defined here.",
3993282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        idx, String8(ot->getName()).string(),
3994282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8(t->getName()).string(),
3995282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ot->getFirstPublicSourcePos().file.string(),
3996282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ot->getFirstPublicSourcePos().line);
3997282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return UNKNOWN_ERROR;
3998282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3999282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mOrderedTypes.replaceAt(t, idx);
4000282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            origOrder.removeAt(i);
4001282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            i--;
4002282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            N--;
4003282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
4004282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
4005282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4006282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t j=0;
4007282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (i=0; i<N; i++) {
4008282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Type> t = origOrder.itemAt(i);
4009282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // There will always be enough room for the remaining types.
4010282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        while (mOrderedTypes.itemAt(j) != NULL) {
4011282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            j++;
4012282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
4013282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mOrderedTypes.replaceAt(t, j);
4014282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
4015282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4016282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
4017282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
4018282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4019282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisp<ResourceTable::Package> ResourceTable::getPackage(const String16& package)
4020282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
4021833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    if (package != mAssetsPackage) {
4022833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        return NULL;
4023282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
4024833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    return mPackages.valueFor(package);
4025282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
4026282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4027282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisp<ResourceTable::Type> ResourceTable::getType(const String16& package,
4028282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                               const String16& type,
4029282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                               const SourcePos& sourcePos,
4030282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                               bool doSetIndex)
4031282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
4032282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Package> p = getPackage(package);
4033282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (p == NULL) {
4034282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NULL;
4035282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
4036282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return p->getType(type, sourcePos, doSetIndex);
4037282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
4038282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4039282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisp<ResourceTable::Entry> ResourceTable::getEntry(const String16& package,
4040282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                 const String16& type,
4041282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                 const String16& name,
4042282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                 const SourcePos& sourcePos,
4043282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                 bool overlay,
4044282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                 const ResTable_config* config,
4045282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                 bool doSetIndex)
4046282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
4047282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Type> t = getType(package, type, sourcePos, doSetIndex);
4048282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (t == NULL) {
4049282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NULL;
4050282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
4051282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return t->getEntry(name, sourcePos, config, doSetIndex, overlay, mBundle->getAutoAddOverlay());
4052282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
4053282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4054e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinskisp<ResourceTable::ConfigList> ResourceTable::getConfigList(const String16& package,
4055e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        const String16& type, const String16& name) const
4056e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski{
4057e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    const size_t packageCount = mOrderedPackages.size();
4058e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    for (size_t pi = 0; pi < packageCount; pi++) {
4059e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        const sp<Package>& p = mOrderedPackages[pi];
4060e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        if (p == NULL || p->getName() != package) {
4061e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski            continue;
4062e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        }
4063e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski
4064e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        const Vector<sp<Type> >& types = p->getOrderedTypes();
4065e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        const size_t typeCount = types.size();
4066e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        for (size_t ti = 0; ti < typeCount; ti++) {
4067e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski            const sp<Type>& t = types[ti];
4068e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski            if (t == NULL || t->getName() != type) {
4069e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                continue;
4070e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski            }
4071e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski
4072e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski            const Vector<sp<ConfigList> >& configs = t->getOrderedConfigs();
4073e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski            const size_t configCount = configs.size();
4074e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski            for (size_t ci = 0; ci < configCount; ci++) {
4075e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                const sp<ConfigList>& cl = configs[ci];
4076e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                if (cl == NULL || cl->getName() != name) {
4077e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                    continue;
4078e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                }
4079e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski
4080e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                return cl;
4081e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski            }
4082e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        }
4083e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    }
4084e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    return NULL;
4085e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski}
4086e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski
4087282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisp<const ResourceTable::Entry> ResourceTable::getEntry(uint32_t resID,
4088282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                       const ResTable_config* config) const
4089282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
4090833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    size_t pid = Res_GETPACKAGE(resID)+1;
4091282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t N = mOrderedPackages.size();
4092282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Package> p;
4093833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    for (size_t i = 0; i < N; i++) {
4094282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Package> check = mOrderedPackages[i];
4095282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (check->getAssignedId() == pid) {
4096282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            p = check;
4097282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            break;
4098282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
4099282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
4101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (p == NULL) {
4102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "warning: Package not found for resource #%08x\n", resID);
4103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NULL;
4104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
4105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int tid = Res_GETTYPE(resID);
4107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (tid < 0 || tid >= (int)p->getOrderedTypes().size()) {
4108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "warning: Type not found for resource #%08x\n", resID);
4109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NULL;
4110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
4111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Type> t = p->getOrderedTypes()[tid];
4112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int eid = Res_GETENTRY(resID);
4114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (eid < 0 || eid >= (int)t->getOrderedConfigs().size()) {
4115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "warning: Entry not found for resource #%08x\n", resID);
4116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NULL;
4117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
4118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<ConfigList> c = t->getOrderedConfigs()[eid];
4120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (c == NULL) {
4121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "warning: Entry not found for resource #%08x\n", resID);
4122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NULL;
4123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
4124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ConfigDescription cdesc;
4126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (config) cdesc = *config;
4127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Entry> e = c->getEntries().valueFor(cdesc);
4128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (c == NULL) {
4129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "warning: Entry configuration not found for resource #%08x\n", resID);
4130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NULL;
4131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
4132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return e;
4134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
4135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiconst ResourceTable::Item* ResourceTable::getItem(uint32_t resID, uint32_t attrID) const
4137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
4138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<const Entry> e = getEntry(resID);
4139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (e == NULL) {
4140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NULL;
4141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
4142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t N = e->getBag().size();
4144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (size_t i=0; i<N; i++) {
4145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const Item& it = e->getBag().valueAt(i);
4146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (it.bagKeyId == 0) {
4147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "warning: ID not yet assigned to '%s' in bag '%s'\n",
4148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(e->getName()).string(),
4149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(e->getBag().keyAt(i)).string());
4150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
4151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (it.bagKeyId == attrID) {
4152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return &it;
4153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
4154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
4155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NULL;
4157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
4158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::getItemValue(
4160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t resID, uint32_t attrID, Res_value* outValue)
4161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
4162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const Item* item = getItem(resID, attrID);
4163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool res = false;
4165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (item != NULL) {
4166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (item->evaluating) {
4167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<const Entry> e = getEntry(resID);
4168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t N = e->getBag().size();
4169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            size_t i;
4170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (i=0; i<N; i++) {
4171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (&e->getBag().valueAt(i) == item) {
4172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    break;
4173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
4174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
4175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "warning: Circular reference detected in key '%s' of bag '%s'\n",
4176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(e->getName()).string(),
4177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(e->getBag().keyAt(i)).string());
4178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;
4179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
4180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        item->evaluating = true;
4181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        res = stringToValue(outValue, NULL, item->value, false, false, item->bagKeyId);
4182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        NOISY(
4183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (res) {
4184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("getItemValue of #%08x[#%08x] (%s): type=#%08x, data=#%08x\n",
4185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       resID, attrID, String8(getEntry(resID)->getName()).string(),
4186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       outValue->dataType, outValue->data);
4187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
4188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("getItemValue of #%08x[#%08x]: failed\n",
4189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       resID, attrID);
4190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
4191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        );
4192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        item->evaluating = false;
4193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
4194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return res;
4195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
419682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski
419782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski/**
419882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * Returns true if the given attribute ID comes from
419982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * a platform version from or after L.
420082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski */
420182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinskibool ResourceTable::isAttributeFromL(uint32_t attrId) {
420282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    const uint32_t baseAttrId = 0x010103f7;
420382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    if ((attrId & 0xffff0000) != (baseAttrId & 0xffff0000)) {
420482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski        return false;
420582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    }
420682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski
420782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    uint32_t specFlags;
420882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    if (!mAssets->getIncludedResources().getResourceFlags(attrId, &specFlags)) {
420982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski        return false;
421082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    }
421182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski
421282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    return (specFlags & ResTable_typeSpec::SPEC_PUBLIC) != 0 &&
421382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski        (attrId & 0x0000ffff) >= (baseAttrId & 0x0000ffff);
421482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski}
421582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski
4216e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinskistatic bool isMinSdkVersionLOrAbove(const Bundle* bundle) {
4217e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    if (bundle->getMinSdkVersion() != NULL && strlen(bundle->getMinSdkVersion()) > 0) {
4218e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        const char firstChar = bundle->getMinSdkVersion()[0];
4219e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        if (firstChar >= 'L' && firstChar <= 'Z') {
4220e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski            // L is the code-name for the v21 release.
4221e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski            return true;
4222e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        }
4223e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski
4224e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        const int minSdk = atoi(bundle->getMinSdkVersion());
4225e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        if (minSdk >= SDK_L) {
4226e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski            return true;
4227e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        }
4228e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    }
4229e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    return false;
4230e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski}
4231e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski
423282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski/**
423382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * Modifies the entries in the resource table to account for compatibility
423482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * issues with older versions of Android.
423582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski *
423682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * This primarily handles the issue of private/public attribute clashes
423782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * in framework resources.
423882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski *
423982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * AAPT has traditionally assigned resource IDs to public attributes,
424082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * and then followed those public definitions with private attributes.
424182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski *
424282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * --- PUBLIC ---
424382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * | 0x01010234 | attr/color
424482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * | 0x01010235 | attr/background
424582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski *
424682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * --- PRIVATE ---
424782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * | 0x01010236 | attr/secret
424882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * | 0x01010237 | attr/shhh
424982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski *
425082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * Each release, when attributes are added, they take the place of the private
425182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * attributes and the private attributes are shifted down again.
425282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski *
425382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * --- PUBLIC ---
425482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * | 0x01010234 | attr/color
425582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * | 0x01010235 | attr/background
425682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * | 0x01010236 | attr/shinyNewAttr
425782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * | 0x01010237 | attr/highlyValuedFeature
425882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski *
425982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * --- PRIVATE ---
426082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * | 0x01010238 | attr/secret
426182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * | 0x01010239 | attr/shhh
426282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski *
426382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * Platform code may look for private attributes set in a theme. If an app
426482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * compiled against a newer version of the platform uses a new public
426582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * attribute that happens to have the same ID as the private attribute
426682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * the older platform is expecting, then the behavior is undefined.
426782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski *
426882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * We get around this by detecting any newly defined attributes (in L),
426982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * copy the resource into a -v21 qualified resource, and delete the
427082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * attribute from the original resource. This ensures that older platforms
427182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * don't see the new attribute, but when running on L+ platforms, the
427282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * attribute will be respected.
427382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski */
427482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinskistatus_t ResourceTable::modifyForCompat(const Bundle* bundle) {
4275e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    if (isMinSdkVersionLOrAbove(bundle)) {
427682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski        // If this app will only ever run on L+ devices,
427782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski        // we don't need to do any compatibility work.
4278e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        return NO_ERROR;
427982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    }
428082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski
428182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    const String16 attr16("attr");
428282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski
428382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    const size_t packageCount = mOrderedPackages.size();
428482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    for (size_t pi = 0; pi < packageCount; pi++) {
428582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski        sp<Package> p = mOrderedPackages.itemAt(pi);
428682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski        if (p == NULL || p->getTypes().size() == 0) {
428782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski            // Empty, skip!
428882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski            continue;
428982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski        }
429082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski
429182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski        const size_t typeCount = p->getOrderedTypes().size();
429282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski        for (size_t ti = 0; ti < typeCount; ti++) {
429382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski            sp<Type> t = p->getOrderedTypes().itemAt(ti);
429482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski            if (t == NULL) {
429582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                continue;
429682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski            }
429782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski
429882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski            const size_t configCount = t->getOrderedConfigs().size();
429982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski            for (size_t ci = 0; ci < configCount; ci++) {
430082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                sp<ConfigList> c = t->getOrderedConfigs().itemAt(ci);
430182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                if (c == NULL) {
430282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                    continue;
430382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                }
430482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski
430582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                Vector<key_value_pair_t<ConfigDescription, sp<Entry> > > entriesToAdd;
430682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                const DefaultKeyedVector<ConfigDescription, sp<Entry> >& entries =
430782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                        c->getEntries();
430882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                const size_t entryCount = entries.size();
430982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                for (size_t ei = 0; ei < entryCount; ei++) {
431082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                    sp<Entry> e = entries.valueAt(ei);
431182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                    if (e == NULL || e->getType() != Entry::TYPE_BAG) {
431282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                        continue;
431382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                    }
431482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski
431582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                    const ConfigDescription& config = entries.keyAt(ei);
431682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                    if (config.sdkVersion >= SDK_L) {
431782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                        // We don't need to do anything if the resource is
431882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                        // already qualified for version 21 or higher.
431982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                        continue;
432082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                    }
432182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski
432282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                    Vector<String16> attributesToRemove;
432382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                    const KeyedVector<String16, Item>& bag = e->getBag();
432482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                    const size_t bagCount = bag.size();
432582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                    for (size_t bi = 0; bi < bagCount; bi++) {
432682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                        const Item& item = bag.valueAt(bi);
432782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                        const uint32_t attrId = getResId(bag.keyAt(bi), &attr16);
432882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                        if (isAttributeFromL(attrId)) {
432982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                            attributesToRemove.add(bag.keyAt(bi));
433082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                        }
433182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                    }
433282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski
433382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                    if (attributesToRemove.isEmpty()) {
433482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                        continue;
433582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                    }
433682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski
433782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                    // Duplicate the entry under the same configuration
433882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                    // but with sdkVersion == SDK_L.
433982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                    ConfigDescription newConfig(config);
434082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                    newConfig.sdkVersion = SDK_L;
434182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                    entriesToAdd.add(key_value_pair_t<ConfigDescription, sp<Entry> >(
434282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                            newConfig, new Entry(*e)));
434382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski
434482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                    // Remove the attribute from the original.
434582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                    for (size_t i = 0; i < attributesToRemove.size(); i++) {
434682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                        e->removeFromBag(attributesToRemove[i]);
434782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                    }
434882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                }
434982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski
435082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                const size_t entriesToAddCount = entriesToAdd.size();
435182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                for (size_t i = 0; i < entriesToAddCount; i++) {
435282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                    if (entries.indexOfKey(entriesToAdd[i].key) >= 0) {
435382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                        // An entry already exists for this config.
435482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                        // That means that any attributes that were
435582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                        // defined in L in the original bag will be overriden
435682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                        // anyways on L devices, so we do nothing.
435782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                        continue;
435882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                    }
435982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski
4360f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski                    if (bundle->getVerbose()) {
4361f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski                        entriesToAdd[i].value->getPos()
4362f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski                                .printf("using v%d attributes; synthesizing resource %s:%s/%s for configuration %s.",
4363f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski                                        SDK_L,
4364f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski                                        String8(p->getName()).string(),
4365f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski                                        String8(t->getName()).string(),
4366f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski                                        String8(entriesToAdd[i].value->getName()).string(),
4367f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski                                        entriesToAdd[i].key.toString().string());
4368f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski                    }
436982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski
4370978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski                    sp<Entry> newEntry = t->getEntry(c->getName(),
4371978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski                            entriesToAdd[i].value->getPos(),
4372978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski                            &entriesToAdd[i].key);
4373978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski
4374978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski                    *newEntry = *entriesToAdd[i].value;
437582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                }
437682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski            }
437782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski        }
437882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    }
437982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    return NO_ERROR;
438082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski}
4381e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski
4382e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinskistatus_t ResourceTable::modifyForCompat(const Bundle* bundle,
4383e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                                        const String16& resourceName,
4384e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                                        const sp<AaptFile>& target,
4385e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                                        const sp<XMLNode>& root) {
4386e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    if (isMinSdkVersionLOrAbove(bundle)) {
4387e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        return NO_ERROR;
4388e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    }
4389e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski
4390e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    if (target->getResourceType() == "" || target->getGroupEntry().toParams().sdkVersion >= SDK_L) {
4391e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        // Skip resources that have no type (AndroidManifest.xml) or are already version qualified with v21
4392e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        // or higher.
4393e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        return NO_ERROR;
4394e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    }
4395e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski
4396e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    Vector<key_value_pair_t<sp<XMLNode>, size_t> > attrsToRemove;
4397e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski
4398e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    Vector<sp<XMLNode> > nodesToVisit;
4399e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    nodesToVisit.push(root);
4400e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    while (!nodesToVisit.isEmpty()) {
4401e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        sp<XMLNode> node = nodesToVisit.top();
4402e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        nodesToVisit.pop();
4403e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski
4404e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        const Vector<XMLNode::attribute_entry>& attrs = node->getAttributes();
4405e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        const size_t attrCount = attrs.size();
4406e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        for (size_t i = 0; i < attrCount; i++) {
4407e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski            const XMLNode::attribute_entry& attr = attrs[i];
4408e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski            if (isAttributeFromL(attr.nameResId)) {
4409e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                attrsToRemove.add(key_value_pair_t<sp<XMLNode>, size_t>(node, i));
4410e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski            }
4411e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        }
4412e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski
4413e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        // Schedule a visit to the children.
4414e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        const Vector<sp<XMLNode> >& children = node->getChildren();
4415e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        const size_t childCount = children.size();
4416e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        for (size_t i = 0; i < childCount; i++) {
4417e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski            nodesToVisit.push(children[i]);
4418e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        }
4419e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    }
4420e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski
4421e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    if (attrsToRemove.isEmpty()) {
4422e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        return NO_ERROR;
4423e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    }
4424e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski
4425e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    ConfigDescription newConfig(target->getGroupEntry().toParams());
4426e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    newConfig.sdkVersion = SDK_L;
4427e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski
4428e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    // Look to see if we already have an overriding v21 configuration.
4429e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    sp<ConfigList> cl = getConfigList(String16(mAssets->getPackage()),
4430e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski            String16(target->getResourceType()), resourceName);
4431aff7c2447df1ddfe094628317b6d22121cd657f8Adam Lesinski    //if (cl == NULL) {
4432aff7c2447df1ddfe094628317b6d22121cd657f8Adam Lesinski    //    fprintf(stderr, "fuuuuck\n");
4433aff7c2447df1ddfe094628317b6d22121cd657f8Adam Lesinski    //}
4434e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    if (cl->getEntries().indexOfKey(newConfig) < 0) {
4435e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        // We don't have an overriding entry for v21, so we must duplicate this one.
4436e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        sp<XMLNode> newRoot = root->clone();
4437e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        sp<AaptFile> newFile = new AaptFile(target->getSourceFile(),
4438e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                AaptGroupEntry(newConfig), target->getResourceType());
4439e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        String8 resPath = String8::format("res/%s/%s",
4440e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                newFile->getGroupEntry().toDirName(target->getResourceType()).string(),
4441aff7c2447df1ddfe094628317b6d22121cd657f8Adam Lesinski                target->getSourceFile().getPathLeaf().string());
4442e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        resPath.convertToResPath();
4443e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski
4444e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        // Add a resource table entry.
4445f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski        if (bundle->getVerbose()) {
4446f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski            SourcePos(target->getSourceFile(), -1).printf(
4447f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski                    "using v%d attributes; synthesizing resource %s:%s/%s for configuration %s.",
4448f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski                    SDK_L,
4449f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski                    mAssets->getPackage().string(),
4450f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski                    newFile->getResourceType().string(),
4451f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski                    String8(resourceName).string(),
4452f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski                    newConfig.toString().string());
4453f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski        }
4454e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski
4455e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        addEntry(SourcePos(),
4456e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                String16(mAssets->getPackage()),
4457e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                String16(target->getResourceType()),
4458e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                resourceName,
4459e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                String16(resPath),
4460e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                NULL,
4461e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                &newConfig);
4462e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski
4463e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        // Schedule this to be compiled.
4464e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        CompileResourceWorkItem item;
4465e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        item.resourceName = resourceName;
4466e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        item.resPath = resPath;
4467e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        item.file = newFile;
4468e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        mWorkQueue.push(item);
4469e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    }
4470e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski
4471e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    const size_t removeCount = attrsToRemove.size();
4472e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    for (size_t i = 0; i < removeCount; i++) {
4473e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        sp<XMLNode> node = attrsToRemove[i].key;
4474e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        size_t attrIndex = attrsToRemove[i].value;
4475e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        const XMLNode::attribute_entry& ae = node->getAttributes()[attrIndex];
4476f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski        if (bundle->getVerbose()) {
4477f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski            SourcePos(node->getFilename(), node->getStartLineNumber()).printf(
4478f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski                    "removing attribute %s%s%s from <%s>",
4479f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski                    String8(ae.ns).string(),
4480f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski                    (ae.ns.size() == 0 ? "" : ":"),
4481f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski                    String8(ae.name).string(),
4482f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski                    String8(node->getElementName()).string());
4483f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski        }
4484e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        node->removeAttribute(attrIndex);
4485e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    }
4486e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski
4487e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    return NO_ERROR;
4488e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski}
4489