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
9de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski#include "AaptUtil.h"
10282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "XMLNode.h"
11282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "ResourceFilter.h"
12282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "ResourceIdCache.h"
13dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski#include "SdkConstants.h"
14282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
159b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski#include <algorithm>
16282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <androidfw/ResourceTypes.h>
17282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <utils/ByteOrder.h>
1882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski#include <utils/TypeHelpers.h>
19282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <stdarg.h>
20282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
21282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#define NOISY(x) //x
22282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
239b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinskistatic const char* kAttrPrivateType = "^attr-private";
249b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski
25e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinskistatus_t compileXmlFile(const Bundle* bundle,
26e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                        const sp<AaptAssets>& assets,
27e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                        const String16& resourceName,
28282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const sp<AaptFile>& target,
29282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ResourceTable* table,
30282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        int options)
31282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
32282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<XMLNode> root = XMLNode::parse(target);
33282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (root == NULL) {
34282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
35282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
36a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin
37e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    return compileXmlFile(bundle, assets, resourceName, root, target, table, options);
38282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
39282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
40e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinskistatus_t compileXmlFile(const Bundle* bundle,
41e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                        const sp<AaptAssets>& assets,
42e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                        const String16& resourceName,
43282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const sp<AaptFile>& target,
44282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const sp<AaptFile>& outTarget,
45282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ResourceTable* table,
46282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        int options)
47282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
48282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<XMLNode> root = XMLNode::parse(target);
49282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (root == NULL) {
50282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
51282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
52282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
53e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    return compileXmlFile(bundle, assets, resourceName, root, outTarget, table, options);
54282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
55282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
56e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinskistatus_t compileXmlFile(const Bundle* bundle,
57e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                        const sp<AaptAssets>& assets,
58e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                        const String16& resourceName,
59282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const sp<XMLNode>& root,
60282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const sp<AaptFile>& target,
61282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ResourceTable* table,
62282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        int options)
63282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
64282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if ((options&XML_COMPILE_STRIP_WHITESPACE) != 0) {
65282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        root->removeWhitespace(true, NULL);
66282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else  if ((options&XML_COMPILE_COMPACT_WHITESPACE) != 0) {
67282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        root->removeWhitespace(false, NULL);
68282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
69282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
70282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if ((options&XML_COMPILE_UTF8) != 0) {
71282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        root->setUTF8(true);
72282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
73282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
74282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool hasErrors = false;
75282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
76282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if ((options&XML_COMPILE_ASSIGN_ATTRIBUTE_IDS) != 0) {
77282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        status_t err = root->assignResourceIds(assets, table);
78282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != NO_ERROR) {
79282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            hasErrors = true;
80282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
81282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
82282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
83282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = root->parseValues(assets, table);
84282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
85282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        hasErrors = true;
86282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
87282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
88282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (hasErrors) {
89282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
90282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
91e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski
92e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    if (table->modifyForCompat(bundle, resourceName, target, root) != NO_ERROR) {
93e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        return UNKNOWN_ERROR;
94e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    }
95282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
96282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    NOISY(printf("Input XML Resource:\n"));
97282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    NOISY(root->print());
98282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    err = root->flatten(target,
99282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            (options&XML_COMPILE_STRIP_COMMENTS) != 0,
100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            (options&XML_COMPILE_STRIP_RAW_VALUES) != 0);
101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return err;
103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    NOISY(printf("Output XML Resource:\n"));
106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    NOISY(ResXMLTree tree;
107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        tree.setTo(target->getData(), target->getSize());
108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printXMLBlock(&tree));
109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    target->setCompressionMethod(ZipEntry::kCompressDeflated);
111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return err;
113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#undef NOISY
116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#define NOISY(x) //x
117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistruct flag_entry
119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char16_t* name;
121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t nameLen;
122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t value;
123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char* description;
124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski};
125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t referenceArray[] =
127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { 'r', 'e', 'f', 'e', 'r', 'e', 'n', 'c', 'e' };
128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t stringArray[] =
129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { 's', 't', 'r', 'i', 'n', 'g' };
130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t integerArray[] =
131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { 'i', 'n', 't', 'e', 'g', 'e', 'r' };
132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t booleanArray[] =
133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { 'b', 'o', 'o', 'l', 'e', 'a', 'n' };
134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t colorArray[] =
135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { 'c', 'o', 'l', 'o', 'r' };
136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t floatArray[] =
137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { 'f', 'l', 'o', 'a', 't' };
138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t dimensionArray[] =
139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { 'd', 'i', 'm', 'e', 'n', 's', 'i', 'o', 'n' };
140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t fractionArray[] =
141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { 'f', 'r', 'a', 'c', 't', 'i', 'o', 'n' };
142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t enumArray[] =
143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { 'e', 'n', 'u', 'm' };
144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t flagsArray[] =
145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { 'f', 'l', 'a', 'g', 's' };
146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const flag_entry gFormatFlags[] = {
148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { referenceArray, sizeof(referenceArray)/2, ResTable_map::TYPE_REFERENCE,
149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      "a reference to another resource, in the form \"<code>@[+][<i>package</i>:]<i>type</i>:<i>name</i></code>\"\n"
150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      "or to a theme attribute in the form \"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>\"."},
151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { stringArray, sizeof(stringArray)/2, ResTable_map::TYPE_STRING,
152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      "a string value, using '\\\\;' to escape characters such as '\\\\n' or '\\\\uxxxx' for a unicode character." },
153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { integerArray, sizeof(integerArray)/2, ResTable_map::TYPE_INTEGER,
154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      "an integer value, such as \"<code>100</code>\"." },
155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { booleanArray, sizeof(booleanArray)/2, ResTable_map::TYPE_BOOLEAN,
156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      "a boolean value, either \"<code>true</code>\" or \"<code>false</code>\"." },
157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { colorArray, sizeof(colorArray)/2, ResTable_map::TYPE_COLOR,
158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      "a color value, in the form of \"<code>#<i>rgb</i></code>\", \"<code>#<i>argb</i></code>\",\n"
159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      "\"<code>#<i>rrggbb</i></code>\", or \"<code>#<i>aarrggbb</i></code>\"." },
160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { floatArray, sizeof(floatArray)/2, ResTable_map::TYPE_FLOAT,
161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      "a floating point value, such as \"<code>1.2</code>\"."},
162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { dimensionArray, sizeof(dimensionArray)/2, ResTable_map::TYPE_DIMENSION,
163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      "a dimension value, which is a floating point number appended with a unit such as \"<code>14.5sp</code>\".\n"
164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      "Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),\n"
165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      "in (inches), mm (millimeters)." },
166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { fractionArray, sizeof(fractionArray)/2, ResTable_map::TYPE_FRACTION,
167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      "a fractional value, which is a floating point number appended with either % or %p, such as \"<code>14.5%</code>\".\n"
168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      "The % suffix always means a percentage of the base size; the optional %p suffix provides a size relative to\n"
169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      "some parent container." },
170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { enumArray, sizeof(enumArray)/2, ResTable_map::TYPE_ENUM, NULL },
171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { flagsArray, sizeof(flagsArray)/2, ResTable_map::TYPE_FLAGS, NULL },
172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { NULL, 0, 0, NULL }
173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski};
174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t suggestedArray[] = { 's', 'u', 'g', 'g', 'e', 's', 't', 'e', 'd' };
176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const flag_entry l10nRequiredFlags[] = {
178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { suggestedArray, sizeof(suggestedArray)/2, ResTable_map::L10N_SUGGESTED, NULL },
179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { NULL, 0, 0, NULL }
180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski};
181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t nulStr[] = { 0 };
183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic uint32_t parse_flags(const char16_t* str, size_t len,
185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                             const flag_entry* flags, bool* outError = NULL)
186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (len > 0 && isspace(*str)) {
188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        str++;
189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        len--;
190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (len > 0 && isspace(str[len-1])) {
192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        len--;
193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char16_t* const end = str + len;
196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t value = 0;
197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (str < end) {
199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const char16_t* div = str;
200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        while (div < end && *div != '|') {
201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            div++;
202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const flag_entry* cur = flags;
205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        while (cur->name) {
206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (strzcmp16(cur->name, cur->nameLen, str, div-str) == 0) {
207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                value |= cur->value;
208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                break;
209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            cur++;
211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!cur->name) {
214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (outError) *outError = true;
215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return 0;
216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        str = div < end ? div+1 : div;
219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (outError) *outError = false;
222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return value;
223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic String16 mayOrMust(int type, int flags)
226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if ((type&(~flags)) == 0) {
228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return String16("<p>Must");
229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return String16("<p>May");
232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic void appendTypeInfo(ResourceTable* outTable, const String16& pkg,
235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String16& typeName, const String16& ident, int type,
236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const flag_entry* flags)
237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool hadType = false;
239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (flags->name) {
240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if ((type&flags->value) != 0 && flags->description != NULL) {
241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String16 fullMsg(mayOrMust(type, flags->value));
242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fullMsg.append(String16(" be "));
243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fullMsg.append(String16(flags->description));
244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            outTable->appendTypeComment(pkg, typeName, ident, fullMsg);
245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            hadType = true;
246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        flags++;
248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (hadType && (type&ResTable_map::TYPE_REFERENCE) == 0) {
250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        outTable->appendTypeComment(pkg, typeName, ident,
251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16("<p>This may also be a reference to a resource (in the form\n"
252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                         "\"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>\") or\n"
253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                         "theme attribute (in the form\n"
254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                         "\"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>\")\n"
255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                         "containing a value of this type."));
256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistruct PendingAttribute
260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 myPackage;
262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const SourcePos sourcePos;
263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const bool appendComment;
264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int32_t type;
265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String16 ident;
266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String16 comment;
267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool hasErrors;
268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool added;
269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    PendingAttribute(String16 _package, const sp<AaptFile>& in,
271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ResXMLTree& block, bool _appendComment)
272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        : myPackage(_package)
273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        , sourcePos(in->getPrintableSource(), block.getLineNumber())
274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        , appendComment(_appendComment)
275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        , type(ResTable_map::TYPE_ANY)
276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        , hasErrors(false)
277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        , added(false)
278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    {
279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t createIfNeeded(ResourceTable* outTable)
282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    {
283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (added || hasErrors) {
284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return NO_ERROR;
285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        added = true;
287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String16 attr16("attr");
289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (outTable->hasBagOrEntry(myPackage, attr16, ident)) {
291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sourcePos.error("Attribute \"%s\" has already been defined\n",
292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(ident).string());
293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            hasErrors = true;
294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return UNKNOWN_ERROR;
295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        char numberStr[16];
298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sprintf(numberStr, "%d", type);
299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        status_t err = outTable->addBag(sourcePos, myPackage,
300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                attr16, ident, String16(""),
301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16("^type"),
302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16(numberStr), NULL, NULL);
303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != NO_ERROR) {
304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            hasErrors = true;
305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return err;
306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        outTable->appendComment(myPackage, attr16, ident, comment, appendComment);
308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //printf("Attribute %s comment: %s\n", String8(ident).string(),
309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //     String8(comment).string());
310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return err;
311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski};
313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic status_t compileAttribute(const sp<AaptFile>& in,
315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 ResXMLTree& block,
316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16& myPackage,
317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 ResourceTable* outTable,
318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 String16* outIdent = NULL,
319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 bool inStyleable = false)
320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    PendingAttribute attr(myPackage, in, block, inStyleable);
322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 attr16("attr");
324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 id16("id");
325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Attribute type constants.
327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 enum16("enum");
328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 flag16("flag");
329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ResXMLTree::event_code_t code;
331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t len;
332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err;
333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t identIdx = block.indexOfAttribute(NULL, "name");
335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (identIdx >= 0) {
336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        attr.ident = String16(block.getAttributeStringValue(identIdx, &len));
337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (outIdent) {
338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            *outIdent = attr.ident;
339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        attr.sourcePos.error("A 'name' attribute is required for <attr>\n");
342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        attr.hasErrors = true;
343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    attr.comment = String16(
346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            block.getComment(&len) ? block.getComment(&len) : nulStr);
347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t typeIdx = block.indexOfAttribute(NULL, "format");
349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (typeIdx >= 0) {
350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String16 typeStr = String16(block.getAttributeStringValue(typeIdx, &len));
351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        attr.type = parse_flags(typeStr.string(), typeStr.size(), gFormatFlags);
352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (attr.type == 0) {
353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            attr.sourcePos.error("Tag <attr> 'format' attribute value \"%s\" not valid\n",
354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(typeStr).string());
355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            attr.hasErrors = true;
356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        attr.createIfNeeded(outTable);
358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else if (!inStyleable) {
359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Attribute definitions outside of styleables always define the
360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // attribute as a generic value.
361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        attr.createIfNeeded(outTable);
362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //printf("Attribute %s: type=0x%08x\n", String8(attr.ident).string(), attr.type);
365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t minIdx = block.indexOfAttribute(NULL, "min");
367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (minIdx >= 0) {
368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String16 val = String16(block.getAttributeStringValue(minIdx, &len));
369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!ResTable::stringToInt(val.string(), val.size(), NULL)) {
370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            attr.sourcePos.error("Tag <attr> 'min' attribute must be a number, not \"%s\"\n",
371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(val).string());
372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            attr.hasErrors = true;
373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        attr.createIfNeeded(outTable);
375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!attr.hasErrors) {
376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            err = outTable->addBag(attr.sourcePos, myPackage, attr16, attr.ident,
377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String16(""), String16("^min"), String16(val), NULL, NULL);
378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (err != NO_ERROR) {
379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                attr.hasErrors = true;
380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t maxIdx = block.indexOfAttribute(NULL, "max");
385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (maxIdx >= 0) {
386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String16 val = String16(block.getAttributeStringValue(maxIdx, &len));
387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!ResTable::stringToInt(val.string(), val.size(), NULL)) {
388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            attr.sourcePos.error("Tag <attr> 'max' attribute must be a number, not \"%s\"\n",
389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(val).string());
390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            attr.hasErrors = true;
391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        attr.createIfNeeded(outTable);
393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!attr.hasErrors) {
394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            err = outTable->addBag(attr.sourcePos, myPackage, attr16, attr.ident,
395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String16(""), String16("^max"), String16(val), NULL, NULL);
396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            attr.hasErrors = true;
397282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
398282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if ((minIdx >= 0 || maxIdx >= 0) && (attr.type&ResTable_map::TYPE_INTEGER) == 0) {
401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        attr.sourcePos.error("Tag <attr> must have format=integer attribute if using max or min\n");
402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        attr.hasErrors = true;
403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t l10nIdx = block.indexOfAttribute(NULL, "localization");
406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (l10nIdx >= 0) {
4074bf58108d442b37ab4adf5ce3a4ecd63472ce254Adam Lesinski        const char16_t* str = block.getAttributeStringValue(l10nIdx, &len);
408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        bool error;
409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        uint32_t l10n_required = parse_flags(str, len, l10nRequiredFlags, &error);
410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (error) {
411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            attr.sourcePos.error("Tag <attr> 'localization' attribute value \"%s\" not valid\n",
412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(str).string());
413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            attr.hasErrors = true;
414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        attr.createIfNeeded(outTable);
416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!attr.hasErrors) {
417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            char buf[11];
418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sprintf(buf, "%d", l10n_required);
419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            err = outTable->addBag(attr.sourcePos, myPackage, attr16, attr.ident,
420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String16(""), String16("^l10n"), String16(buf), NULL, NULL);
421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (err != NO_ERROR) {
422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                attr.hasErrors = true;
423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
426282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String16 enumOrFlagsComment;
428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (code == ResXMLTree::START_TAG) {
431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            uint32_t localType = 0;
432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (strcmp16(block.getElementName(&len), enum16.string()) == 0) {
433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                localType = ResTable_map::TYPE_ENUM;
434282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), flag16.string()) == 0) {
435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                localType = ResTable_map::TYPE_FLAGS;
436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
437282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos(in->getPrintableSource(), block.getLineNumber())
438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        .error("Tag <%s> can not appear inside <attr>, only <enum> or <flag>\n",
439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8(block.getElementName(&len)).string());
440282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return UNKNOWN_ERROR;
441282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            attr.createIfNeeded(outTable);
444282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
445282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (attr.type == ResTable_map::TYPE_ANY) {
446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // No type was explicitly stated, so supplying enum tags
447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // implicitly creates an enum or flag.
448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                attr.type = 0;
449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if ((attr.type&(ResTable_map::TYPE_ENUM|ResTable_map::TYPE_FLAGS)) == 0) {
452282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Wasn't originally specified as an enum, so update its type.
453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                attr.type |= localType;
454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!attr.hasErrors) {
455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    char numberStr[16];
456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sprintf(numberStr, "%d", attr.type);
457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    err = outTable->addBag(SourcePos(in->getPrintableSource(), block.getLineNumber()),
458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            myPackage, attr16, attr.ident, String16(""),
459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            String16("^type"), String16(numberStr), NULL, NULL, true);
460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (err != NO_ERROR) {
461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        attr.hasErrors = true;
462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if ((uint32_t)(attr.type&(ResTable_map::TYPE_ENUM|ResTable_map::TYPE_FLAGS)) != localType) {
465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (localType == ResTable_map::TYPE_ENUM) {
466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    SourcePos(in->getPrintableSource(), block.getLineNumber())
467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            .error("<enum> attribute can not be used inside a flags format\n");
468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    attr.hasErrors = true;
469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    SourcePos(in->getPrintableSource(), block.getLineNumber())
471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            .error("<flag> attribute can not be used inside a enum format\n");
472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    attr.hasErrors = true;
473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String16 itemIdent;
477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ssize_t itemIdentIdx = block.indexOfAttribute(NULL, "name");
478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (itemIdentIdx >= 0) {
479282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                itemIdent = String16(block.getAttributeStringValue(itemIdentIdx, &len));
480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos(in->getPrintableSource(), block.getLineNumber())
482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        .error("A 'name' attribute is required for <enum> or <flag>\n");
483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                attr.hasErrors = true;
484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String16 value;
487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ssize_t valueIdx = block.indexOfAttribute(NULL, "value");
488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (valueIdx >= 0) {
489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                value = String16(block.getAttributeStringValue(valueIdx, &len));
490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos(in->getPrintableSource(), block.getLineNumber())
492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        .error("A 'value' attribute is required for <enum> or <flag>\n");
493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                attr.hasErrors = true;
494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!attr.hasErrors && !ResTable::stringToInt(value.string(), value.size(), NULL)) {
496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos(in->getPrintableSource(), block.getLineNumber())
497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        .error("Tag <enum> or <flag> 'value' attribute must be a number,"
498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        " not \"%s\"\n",
499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8(value).string());
500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                attr.hasErrors = true;
501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!attr.hasErrors) {
504282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (enumOrFlagsComment.size() == 0) {
505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    enumOrFlagsComment.append(mayOrMust(attr.type,
506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            ResTable_map::TYPE_ENUM|ResTable_map::TYPE_FLAGS));
507282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    enumOrFlagsComment.append((attr.type&ResTable_map::TYPE_ENUM)
508282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       ? String16(" be one of the following constant values.")
509282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       : String16(" be one or more (separated by '|') of the following constant values."));
510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    enumOrFlagsComment.append(String16("</p>\n<table>\n"
511282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                "<colgroup align=\"left\" />\n"
512282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                "<colgroup align=\"left\" />\n"
513282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                "<colgroup align=\"left\" />\n"
514282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                "<tr><th>Constant</th><th>Value</th><th>Description</th></tr>"));
515282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
516282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
517282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                enumOrFlagsComment.append(String16("\n<tr><td><code>"));
518282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                enumOrFlagsComment.append(itemIdent);
519282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                enumOrFlagsComment.append(String16("</code></td><td>"));
520282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                enumOrFlagsComment.append(value);
521282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                enumOrFlagsComment.append(String16("</td><td>"));
522282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (block.getComment(&len)) {
523282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    enumOrFlagsComment.append(String16(block.getComment(&len)));
524282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
525282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                enumOrFlagsComment.append(String16("</td></tr>"));
526282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
527282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                err = outTable->addBag(SourcePos(in->getPrintableSource(), block.getLineNumber()),
528282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       myPackage,
529282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       attr16, attr.ident, String16(""),
530282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       itemIdent, value, NULL, NULL, false, true);
531282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (err != NO_ERROR) {
532282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    attr.hasErrors = true;
533282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
534282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
535282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else if (code == ResXMLTree::END_TAG) {
536282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (strcmp16(block.getElementName(&len), attr16.string()) == 0) {
537282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                break;
538282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
539282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if ((attr.type&ResTable_map::TYPE_ENUM) != 0) {
540282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (strcmp16(block.getElementName(&len), enum16.string()) != 0) {
541282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    SourcePos(in->getPrintableSource(), block.getLineNumber())
542282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            .error("Found tag </%s> where </enum> is expected\n",
543282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            String8(block.getElementName(&len)).string());
544282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return UNKNOWN_ERROR;
545282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
546282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
547282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (strcmp16(block.getElementName(&len), flag16.string()) != 0) {
548282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    SourcePos(in->getPrintableSource(), block.getLineNumber())
549282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            .error("Found tag </%s> where </flag> is expected\n",
550282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            String8(block.getElementName(&len)).string());
551282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return UNKNOWN_ERROR;
552282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
554282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
555282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
556282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
557282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (!attr.hasErrors && attr.added) {
558282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        appendTypeInfo(outTable, myPackage, attr16, attr.ident, attr.type, gFormatFlags);
559282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
560282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
561282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (!attr.hasErrors && enumOrFlagsComment.size() > 0) {
562282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        enumOrFlagsComment.append(String16("\n</table>"));
563282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        outTable->appendTypeComment(myPackage, attr16, attr.ident, enumOrFlagsComment);
564282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
565282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
566282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
567282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
568282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
569282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
570282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool localeIsDefined(const ResTable_config& config)
571282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return config.locale == 0;
573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t parseAndAddBag(Bundle* bundle,
576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const sp<AaptFile>& in,
577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ResXMLTree* block,
578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const ResTable_config& config,
579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const String16& myPackage,
580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const String16& curType,
581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const String16& ident,
582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const String16& parentIdent,
583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const String16& itemIdent,
584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        int32_t curFormat,
585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        bool isFormatted,
586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const String16& product,
587a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                        PseudolocalizationMethod pseudolocalize,
588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const bool overwrite,
589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ResourceTable* outTable)
590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err;
592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 item16("item");
593a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin
594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String16 str;
595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Vector<StringPool::entry_style_span> spans;
596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    err = parseStyledString(bundle, in->getPrintableSource().string(),
597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            block, item16, &str, &spans, isFormatted,
598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            pseudolocalize);
599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return err;
601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    NOISY(printf("Adding resource bag entry l=%c%c c=%c%c orien=%d d=%d "
604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 " pid=%s, bag=%s, id=%s: %s\n",
605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 config.language[0], config.language[1],
606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 config.country[0], config.country[1],
607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 config.orientation, config.density,
608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 String8(parentIdent).string(),
609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 String8(ident).string(),
610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 String8(itemIdent).string(),
611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 String8(str).string()));
612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    err = outTable->addBag(SourcePos(in->getPrintableSource(), block->getLineNumber()),
614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           myPackage, curType, ident, parentIdent, itemIdent, str,
615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           &spans, &config, overwrite, false, curFormat);
616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return err;
617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
620282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Returns true if needle is one of the elements in the comma-separated list
621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * haystack, false otherwise.
622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool isInProductList(const String16& needle, const String16& haystack) {
624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char16_t *needle2 = needle.string();
625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char16_t *haystack2 = haystack.string();
626282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t needlesize = needle.size();
627282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
628282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (*haystack2 != '\0') {
629282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (strncmp16(haystack2, needle2, needlesize) == 0) {
630282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (haystack2[needlesize] == '\0' || haystack2[needlesize] == ',') {
631282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return true;
632282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
633282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
634282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        while (*haystack2 != '\0' && *haystack2 != ',') {
636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            haystack2++;
637282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (*haystack2 == ',') {
639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            haystack2++;
640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
644282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
645282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
6468ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski/*
6478ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski * A simple container that holds a resource type and name. It is ordered first by type then
6488ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski * by name.
6498ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski */
6508ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinskistruct type_ident_pair_t {
6518ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    String16 type;
6528ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    String16 ident;
6538ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski
6548ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    type_ident_pair_t() { };
6558ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    type_ident_pair_t(const String16& t, const String16& i) : type(t), ident(i) { }
6568ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    type_ident_pair_t(const type_ident_pair_t& o) : type(o.type), ident(o.ident) { }
6578ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    inline bool operator < (const type_ident_pair_t& o) const {
6588ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski        int cmp = compare_type(type, o.type);
6598ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski        if (cmp < 0) {
6608ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski            return true;
6618ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski        } else if (cmp > 0) {
6628ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski            return false;
6638ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski        } else {
6648ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski            return strictly_order_type(ident, o.ident);
6658ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski        }
6668ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    }
6678ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski};
6688ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski
6698ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski
670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t parseAndAddEntry(Bundle* bundle,
671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const sp<AaptFile>& in,
672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ResXMLTree* block,
673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const ResTable_config& config,
674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const String16& myPackage,
675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const String16& curType,
676282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const String16& ident,
677282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const String16& curTag,
678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        bool curIsStyled,
679282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        int32_t curFormat,
680282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        bool isFormatted,
681282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const String16& product,
682a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                        PseudolocalizationMethod pseudolocalize,
683282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const bool overwrite,
6848ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                        KeyedVector<type_ident_pair_t, bool>* skippedResourceNames,
685282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ResourceTable* outTable)
686282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
687282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err;
688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String16 str;
690282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Vector<StringPool::entry_style_span> spans;
691282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    err = parseStyledString(bundle, in->getPrintableSource().string(), block,
692282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            curTag, &str, curIsStyled ? &spans : NULL,
693282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            isFormatted, pseudolocalize);
694282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err < NO_ERROR) {
696282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return err;
697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*
700282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * If a product type was specified on the command line
701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * and also in the string, and the two are not the same,
702282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * return without adding the string.
703282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
704282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
705282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char *bundleProduct = bundle->getProduct();
706282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundleProduct == NULL) {
707282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        bundleProduct = "";
708282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
709282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
710282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (product.size() != 0) {
711282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        /*
712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         * If the command-line-specified product is empty, only "default"
713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         * matches.  Other variants are skipped.  This is so generation
714282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         * of the R.java file when the product is not known is predictable.
715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         */
716282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
717282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (bundleProduct[0] == '\0') {
718282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (strcmp16(String16("default").string(), product.string()) != 0) {
7198ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                /*
7208ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                 * This string has a product other than 'default'. Do not add it,
7218ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                 * but record it so that if we do not see the same string with
7228ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                 * product 'default' or no product, then report an error.
7238ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                 */
7248ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                skippedResourceNames->replaceValueFor(
7258ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                        type_ident_pair_t(curType, ident), true);
726282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return NO_ERROR;
727282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
728282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
729282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            /*
730282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             * The command-line product is not empty.
731282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             * If the product for this string is on the command-line list,
732282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             * it matches.  "default" also matches, but only if nothing
733282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             * else has matched already.
734282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             */
735282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
736282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (isInProductList(product, String16(bundleProduct))) {
737282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ;
738282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(String16("default").string(), product.string()) == 0 &&
739282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       !outTable->hasBagOrEntry(myPackage, curType, ident, config)) {
740282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ;
741282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
742282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return NO_ERROR;
743282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
744282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
745282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
746282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
747282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    NOISY(printf("Adding resource entry l=%c%c c=%c%c orien=%d d=%d id=%s: %s\n",
748282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 config.language[0], config.language[1],
749282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 config.country[0], config.country[1],
750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 config.orientation, config.density,
751282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 String8(ident).string(), String8(str).string()));
752282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
753282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    err = outTable->addEntry(SourcePos(in->getPrintableSource(), block->getLineNumber()),
754282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                             myPackage, curType, ident, str, &spans, &config,
755282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                             false, curFormat, overwrite);
756282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
757282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return err;
758282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
759282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
760282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t compileResourceFile(Bundle* bundle,
761282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                             const sp<AaptAssets>& assets,
762282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                             const sp<AaptFile>& in,
763282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                             const ResTable_config& defParams,
764282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                             const bool overwrite,
765282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                             ResourceTable* outTable)
766282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
767282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ResXMLTree block;
768282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = parseXMLResource(in, &block, false, true);
769282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
770282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return err;
771282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Top-level tag.
774282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 resources16("resources");
775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
776282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Identifier declaration tags.
777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 declare_styleable16("declare-styleable");
778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 attr16("attr");
779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Data creation organizational tags.
781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 string16("string");
782282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 drawable16("drawable");
783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 color16("color");
784282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 bool16("bool");
785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 integer16("integer");
786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 dimen16("dimen");
787282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 fraction16("fraction");
788282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 style16("style");
789282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 plurals16("plurals");
790282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 array16("array");
791282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 string_array16("string-array");
792282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 integer_array16("integer-array");
793282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 public16("public");
794282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 public_padding16("public-padding");
795282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 private_symbols16("private-symbols");
796282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 java_symbol16("java-symbol");
797282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 add_resource16("add-resource");
798282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 skip16("skip");
799282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 eat_comment16("eat-comment");
800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
801282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Data creation tags.
802282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 bag16("bag");
803282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 item16("item");
804282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
805282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Attribute type constants.
806282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 enum16("enum");
807282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
808282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // plural values
809282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 other16("other");
810282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 quantityOther16("^other");
811282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 zero16("zero");
812282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 quantityZero16("^zero");
813282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 one16("one");
814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 quantityOne16("^one");
815282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 two16("two");
816282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 quantityTwo16("^two");
817282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 few16("few");
818282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 quantityFew16("^few");
819282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 many16("many");
820282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 quantityMany16("^many");
821282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
822282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // useful attribute names and special values
823282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 name16("name");
824282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 translatable16("translatable");
825282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 formatted16("formatted");
826282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 false16("false");
827282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
828282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 myPackage(assets->getPackage());
829282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
830282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool hasErrors = false;
831282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
832282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool fileIsTranslatable = true;
833282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (strstr(in->getPrintableSource().string(), "donottranslate") != NULL) {
834282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fileIsTranslatable = false;
835282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
836282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
837282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    DefaultKeyedVector<String16, uint32_t> nextPublicId(0);
838282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
8398ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    // Stores the resource names that were skipped. Typically this happens when
8408ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    // AAPT is invoked without a product specified and a resource has no
8418ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    // 'default' product attribute.
8428ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    KeyedVector<type_ident_pair_t, bool> skippedResourceNames;
8438ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski
844282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ResXMLTree::event_code_t code;
845282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    do {
846282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        code = block.next();
847282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } while (code == ResXMLTree::START_NAMESPACE);
848282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
849282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t len;
850282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (code != ResXMLTree::START_TAG) {
851282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                "No start tag found\n");
853282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
854282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
855282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (strcmp16(block.getElementName(&len), resources16.string()) != 0) {
856282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
857282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                "Invalid start tag %s\n", String8(block.getElementName(&len)).string());
858282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
859282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
860282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
861282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ResTable_config curParams(defParams);
862282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
863282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ResTable_config pseudoParams(curParams);
864a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        pseudoParams.language[0] = 'e';
865a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        pseudoParams.language[1] = 'n';
866a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        pseudoParams.country[0] = 'X';
867a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        pseudoParams.country[1] = 'A';
868a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin
869a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin    ResTable_config pseudoBidiParams(curParams);
870a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        pseudoBidiParams.language[0] = 'a';
871a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        pseudoBidiParams.language[1] = 'r';
872a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        pseudoBidiParams.country[0] = 'X';
873a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        pseudoBidiParams.country[1] = 'B';
874282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
87547843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk    // We should skip resources for pseudolocales if they were
87647843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk    // already added automatically. This is a fix for a transition period when
87747843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk    // manually pseudolocalized resources may be expected.
87847843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk    // TODO: remove this check after next SDK version release.
87947843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk    if ((bundle->getPseudolocalize() & PSEUDO_ACCENTED &&
88047843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk         curParams.locale == pseudoParams.locale) ||
88147843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk        (bundle->getPseudolocalize() & PSEUDO_BIDI &&
88247843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk         curParams.locale == pseudoBidiParams.locale)) {
88347843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk        SourcePos(in->getPrintableSource(), 0).warning(
88447843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk                "Resource file %s is skipped as pseudolocalization"
88547843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk                " was done automatically.",
88647843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk                in->getPrintableSource().string());
88747843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk        return NO_ERROR;
88847843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk    }
88947843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk
890282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
891282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (code == ResXMLTree::START_TAG) {
892282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const String16* curTag = NULL;
893282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String16 curType;
894282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int32_t curFormat = ResTable_map::TYPE_ANY;
895282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool curIsBag = false;
896282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool curIsBagReplaceOnOverwrite = false;
897282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool curIsStyled = false;
898282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool curIsPseudolocalizable = false;
899282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool curIsFormatted = fileIsTranslatable;
900282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool localHasErrors = false;
901282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
902282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (strcmp16(block.getElementName(&len), skip16.string()) == 0) {
903282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                while ((code=block.next()) != ResXMLTree::END_DOCUMENT
904282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        && code != ResXMLTree::BAD_DOCUMENT) {
905282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (code == ResXMLTree::END_TAG) {
906282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(block.getElementName(&len), skip16.string()) == 0) {
907282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            break;
908282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
909282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
910282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
911282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
912282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
913282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), eat_comment16.string()) == 0) {
914282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                while ((code=block.next()) != ResXMLTree::END_DOCUMENT
915282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        && code != ResXMLTree::BAD_DOCUMENT) {
916282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (code == ResXMLTree::END_TAG) {
917282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(block.getElementName(&len), eat_comment16.string()) == 0) {
918282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            break;
919282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
920282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
921282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
922282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
923282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
924282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), public16.string()) == 0) {
925282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos srcPos(in->getPrintableSource(), block.getLineNumber());
926282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
927282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 type;
928282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t typeIdx = block.indexOfAttribute(NULL, "type");
929282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (typeIdx < 0) {
930282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("A 'type' attribute is required for <public>\n");
931282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
932282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
933282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                type = String16(block.getAttributeStringValue(typeIdx, &len));
934282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
935282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 name;
936282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t nameIdx = block.indexOfAttribute(NULL, "name");
937282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (nameIdx < 0) {
938282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("A 'name' attribute is required for <public>\n");
939282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
940282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
941282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                name = String16(block.getAttributeStringValue(nameIdx, &len));
942282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
943282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                uint32_t ident = 0;
944282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t identIdx = block.indexOfAttribute(NULL, "id");
945282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (identIdx >= 0) {
946282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    const char16_t* identStr = block.getAttributeStringValue(identIdx, &len);
947282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    Res_value identValue;
948282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (!ResTable::stringToInt(identStr, len, &identValue)) {
949282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        srcPos.error("Given 'id' attribute is not an integer: %s\n",
950282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                String8(block.getAttributeStringValue(identIdx, &len)).string());
951282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasErrors = localHasErrors = true;
952282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else {
953282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ident = identValue.data;
954282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        nextPublicId.replaceValueFor(type, ident+1);
955282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
956282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else if (nextPublicId.indexOfKey(type) < 0) {
957282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("No 'id' attribute supplied <public>,"
958282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            " and no previous id defined in this file.\n");
959282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
960282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else if (!localHasErrors) {
961282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    ident = nextPublicId.valueFor(type);
962282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    nextPublicId.replaceValueFor(type, ident+1);
963282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
964282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
965282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!localHasErrors) {
966282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    err = outTable->addPublic(srcPos, myPackage, type, name, ident);
967282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (err < NO_ERROR) {
968282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasErrors = localHasErrors = true;
969282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
970282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
971282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!localHasErrors) {
972282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sp<AaptSymbols> symbols = assets->getSymbolsFor(String8("R"));
973282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (symbols != NULL) {
974282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        symbols = symbols->addNestedSymbol(String8(type), srcPos);
975282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
976282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (symbols != NULL) {
977282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        symbols->makeSymbolPublic(String8(name), srcPos);
978282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String16 comment(
979282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            block.getComment(&len) ? block.getComment(&len) : nulStr);
980282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        symbols->appendComment(String8(name), comment, srcPos);
981282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else {
982282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        srcPos.error("Unable to create symbols!\n");
983282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasErrors = localHasErrors = true;
984282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
985282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
986282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
987282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
988282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (code == ResXMLTree::END_TAG) {
989282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(block.getElementName(&len), public16.string()) == 0) {
990282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            break;
991282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
992282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
993282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
994282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
995282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
996282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), public_padding16.string()) == 0) {
997282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos srcPos(in->getPrintableSource(), block.getLineNumber());
998282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
999282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 type;
1000282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t typeIdx = block.indexOfAttribute(NULL, "type");
1001282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (typeIdx < 0) {
1002282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("A 'type' attribute is required for <public-padding>\n");
1003282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1004282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1005282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                type = String16(block.getAttributeStringValue(typeIdx, &len));
1006282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1007282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 name;
1008282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t nameIdx = block.indexOfAttribute(NULL, "name");
1009282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (nameIdx < 0) {
1010282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("A 'name' attribute is required for <public-padding>\n");
1011282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1012282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1013282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                name = String16(block.getAttributeStringValue(nameIdx, &len));
1014282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1015282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                uint32_t start = 0;
1016282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t startIdx = block.indexOfAttribute(NULL, "start");
1017282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (startIdx >= 0) {
1018282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    const char16_t* startStr = block.getAttributeStringValue(startIdx, &len);
1019282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    Res_value startValue;
1020282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (!ResTable::stringToInt(startStr, len, &startValue)) {
1021282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        srcPos.error("Given 'start' attribute is not an integer: %s\n",
1022282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                String8(block.getAttributeStringValue(startIdx, &len)).string());
1023282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasErrors = localHasErrors = true;
1024282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else {
1025282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        start = startValue.data;
1026282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1027282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else if (nextPublicId.indexOfKey(type) < 0) {
1028282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("No 'start' attribute supplied <public-padding>,"
1029282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            " and no previous id defined in this file.\n");
1030282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1031282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else if (!localHasErrors) {
1032282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    start = nextPublicId.valueFor(type);
1033282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1034282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1035282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                uint32_t end = 0;
1036282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t endIdx = block.indexOfAttribute(NULL, "end");
1037282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (endIdx >= 0) {
1038282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    const char16_t* endStr = block.getAttributeStringValue(endIdx, &len);
1039282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    Res_value endValue;
1040282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (!ResTable::stringToInt(endStr, len, &endValue)) {
1041282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        srcPos.error("Given 'end' attribute is not an integer: %s\n",
1042282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                String8(block.getAttributeStringValue(endIdx, &len)).string());
1043282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasErrors = localHasErrors = true;
1044282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else {
1045282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        end = endValue.data;
1046282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1047282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1048282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("No 'end' attribute supplied <public-padding>\n");
1049282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1050282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1051282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1052282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (end >= start) {
1053282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    nextPublicId.replaceValueFor(type, end+1);
1054282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1055282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("Padding start '%ul' is after end '%ul'\n",
1056282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            start, end);
1057282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1058282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1059282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1060282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 comment(
1061282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    block.getComment(&len) ? block.getComment(&len) : nulStr);
1062282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                for (uint32_t curIdent=start; curIdent<=end; curIdent++) {
1063282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (localHasErrors) {
1064282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        break;
1065282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1066282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String16 curName(name);
1067282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    char buf[64];
1068282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sprintf(buf, "%d", (int)(end-curIdent+1));
1069282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    curName.append(String16(buf));
1070282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1071282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    err = outTable->addEntry(srcPos, myPackage, type, curName,
1072282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                             String16("padding"), NULL, &curParams, false,
1073282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                             ResTable_map::TYPE_STRING, overwrite);
1074282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (err < NO_ERROR) {
1075282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasErrors = localHasErrors = true;
1076282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        break;
1077282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1078282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    err = outTable->addPublic(srcPos, myPackage, type,
1079282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            curName, curIdent);
1080282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (err < NO_ERROR) {
1081282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasErrors = localHasErrors = true;
1082282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        break;
1083282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1084282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sp<AaptSymbols> symbols = assets->getSymbolsFor(String8("R"));
1085282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (symbols != NULL) {
1086282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        symbols = symbols->addNestedSymbol(String8(type), srcPos);
1087282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1088282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (symbols != NULL) {
1089282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        symbols->makeSymbolPublic(String8(curName), srcPos);
1090282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        symbols->appendComment(String8(curName), comment, srcPos);
1091282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else {
1092282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        srcPos.error("Unable to create symbols!\n");
1093282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasErrors = localHasErrors = true;
1094282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1095282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1096282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1097282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
1098282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (code == ResXMLTree::END_TAG) {
1099282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(block.getElementName(&len), public_padding16.string()) == 0) {
1100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            break;
1101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
1105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), private_symbols16.string()) == 0) {
1107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 pkg;
1108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t pkgIdx = block.indexOfAttribute(NULL, "package");
1109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (pkgIdx < 0) {
1110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            "A 'package' attribute is required for <private-symbols>\n");
1112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                pkg = String16(block.getAttributeStringValue(pkgIdx, &len));
1115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!localHasErrors) {
1116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    assets->setSymbolsPrivatePackage(String8(pkg));
1117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
1120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (code == ResXMLTree::END_TAG) {
1121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(block.getElementName(&len), private_symbols16.string()) == 0) {
1122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            break;
1123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
1127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), java_symbol16.string()) == 0) {
1129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos srcPos(in->getPrintableSource(), block.getLineNumber());
1130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 type;
1132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t typeIdx = block.indexOfAttribute(NULL, "type");
1133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (typeIdx < 0) {
1134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("A 'type' attribute is required for <public>\n");
1135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                type = String16(block.getAttributeStringValue(typeIdx, &len));
1138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 name;
1140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t nameIdx = block.indexOfAttribute(NULL, "name");
1141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (nameIdx < 0) {
1142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("A 'name' attribute is required for <public>\n");
1143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                name = String16(block.getAttributeStringValue(nameIdx, &len));
1146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<AaptSymbols> symbols = assets->getJavaSymbolsFor(String8("R"));
1148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (symbols != NULL) {
1149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    symbols = symbols->addNestedSymbol(String8(type), srcPos);
1150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (symbols != NULL) {
1152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    symbols->makeSymbolJavaSymbol(String8(name), srcPos);
1153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String16 comment(
1154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        block.getComment(&len) ? block.getComment(&len) : nulStr);
1155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    symbols->appendComment(String8(name), comment, srcPos);
1156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("Unable to create symbols!\n");
1158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
1162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (code == ResXMLTree::END_TAG) {
1163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(block.getElementName(&len), java_symbol16.string()) == 0) {
1164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            break;
1165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
1169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), add_resource16.string()) == 0) {
1172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos srcPos(in->getPrintableSource(), block.getLineNumber());
1173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 typeName;
1175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t typeIdx = block.indexOfAttribute(NULL, "type");
1176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (typeIdx < 0) {
1177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("A 'type' attribute is required for <add-resource>\n");
1178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                typeName = String16(block.getAttributeStringValue(typeIdx, &len));
1181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 name;
1183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t nameIdx = block.indexOfAttribute(NULL, "name");
1184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (nameIdx < 0) {
1185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("A 'name' attribute is required for <add-resource>\n");
1186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                name = String16(block.getAttributeStringValue(nameIdx, &len));
1189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                outTable->canAddEntry(srcPos, myPackage, typeName, name);
1191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
1193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (code == ResXMLTree::END_TAG) {
1194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(block.getElementName(&len), add_resource16.string()) == 0) {
1195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            break;
1196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
1200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), declare_styleable16.string()) == 0) {
1202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos srcPos(in->getPrintableSource(), block.getLineNumber());
1203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 ident;
1205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t identIdx = block.indexOfAttribute(NULL, "name");
1206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (identIdx < 0) {
1207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("A 'name' attribute is required for <declare-styleable>\n");
1208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ident = String16(block.getAttributeStringValue(identIdx, &len));
1211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<AaptSymbols> symbols = assets->getSymbolsFor(String8("R"));
1213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!localHasErrors) {
1214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (symbols != NULL) {
1215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        symbols = symbols->addNestedSymbol(String8("styleable"), srcPos);
1216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sp<AaptSymbols> styleSymbols = symbols;
1218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (symbols != NULL) {
1219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        symbols = symbols->addNestedSymbol(String8(ident), srcPos);
1220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (symbols == NULL) {
1222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        srcPos.error("Unable to create symbols!\n");
1223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        return UNKNOWN_ERROR;
1224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String16 comment(
1227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        block.getComment(&len) ? block.getComment(&len) : nulStr);
1228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    styleSymbols->appendComment(String8(ident), comment, srcPos);
1229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    symbols = NULL;
1231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
1234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (code == ResXMLTree::START_TAG) {
1235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(block.getElementName(&len), skip16.string()) == 0) {
1236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            while ((code=block.next()) != ResXMLTree::END_DOCUMENT
1237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                   && code != ResXMLTree::BAD_DOCUMENT) {
1238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                if (code == ResXMLTree::END_TAG) {
1239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    if (strcmp16(block.getElementName(&len), skip16.string()) == 0) {
1240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        break;
1241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    }
1242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                }
1243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            continue;
1245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else if (strcmp16(block.getElementName(&len), eat_comment16.string()) == 0) {
1246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            while ((code=block.next()) != ResXMLTree::END_DOCUMENT
1247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                   && code != ResXMLTree::BAD_DOCUMENT) {
1248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                if (code == ResXMLTree::END_TAG) {
1249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    if (strcmp16(block.getElementName(&len), eat_comment16.string()) == 0) {
1250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        break;
1251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    }
1252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                }
1253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            continue;
1255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else if (strcmp16(block.getElementName(&len), attr16.string()) != 0) {
1256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    "Tag <%s> can not appear inside <declare-styleable>, only <attr>\n",
1258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    String8(block.getElementName(&len)).string());
1259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            return UNKNOWN_ERROR;
1260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String16 comment(
1263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            block.getComment(&len) ? block.getComment(&len) : nulStr);
1264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String16 itemIdent;
1265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        err = compileAttribute(in, block, myPackage, outTable, &itemIdent, true);
1266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (err != NO_ERROR) {
1267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            hasErrors = localHasErrors = true;
1268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (symbols != NULL) {
1271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            SourcePos srcPos(String8(in->getPrintableSource()), block.getLineNumber());
1272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            symbols->addSymbol(String8(itemIdent), 0, srcPos);
1273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            symbols->appendComment(String8(itemIdent), comment, srcPos);
1274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            //printf("Attribute %s comment: %s\n", String8(itemIdent).string(),
1275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            //     String8(comment).string());
1276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (code == ResXMLTree::END_TAG) {
1278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(block.getElementName(&len), declare_styleable16.string()) == 0) {
1279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            break;
1280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                "Found tag </%s> where </attr> is expected\n",
1284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                String8(block.getElementName(&len)).string());
1285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        return UNKNOWN_ERROR;
1286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
1289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), attr16.string()) == 0) {
1291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                err = compileAttribute(in, block, myPackage, outTable, NULL);
1292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (err != NO_ERROR) {
1293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = true;
1294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
1296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), item16.string()) == 0) {
1298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &item16;
1299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t attri = block.indexOfAttribute(NULL, "type");
1300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (attri >= 0) {
1301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    curType = String16(block.getAttributeStringValue(attri, &len));
1302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    ssize_t formatIdx = block.indexOfAttribute(NULL, "format");
1303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (formatIdx >= 0) {
1304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String16 formatStr = String16(block.getAttributeStringValue(
1305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                formatIdx, &len));
1306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        curFormat = parse_flags(formatStr.string(), formatStr.size(),
1307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                gFormatFlags);
1308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (curFormat == 0) {
1309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    "Tag <item> 'format' attribute value \"%s\" not valid\n",
1311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    String8(formatStr).string());
1312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            hasErrors = localHasErrors = true;
1313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            "A 'type' attribute is required for <item>\n");
1318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsStyled = true;
1321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), string16.string()) == 0) {
1322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Note the existence and locale of every string we process
132391447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath                char rawLocale[RESTABLE_MAX_LOCALE_LEN];
132491447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath                curParams.getBcp47Locale(rawLocale);
1325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String8 locale(rawLocale);
1326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 name;
1327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 translatable;
1328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 formatted;
1329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                size_t n = block.getAttributeCount();
1331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                for (size_t i = 0; i < n; i++) {
1332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    size_t length;
13334bf58108d442b37ab4adf5ce3a4ecd63472ce254Adam Lesinski                    const char16_t* attr = block.getAttributeName(i, &length);
1334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (strcmp16(attr, name16.string()) == 0) {
1335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        name.setTo(block.getAttributeStringValue(i, &length));
1336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (strcmp16(attr, translatable16.string()) == 0) {
1337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        translatable.setTo(block.getAttributeStringValue(i, &length));
1338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (strcmp16(attr, formatted16.string()) == 0) {
1339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        formatted.setTo(block.getAttributeStringValue(i, &length));
1340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (name.size() > 0) {
1344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (translatable == false16) {
1345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        curIsFormatted = false;
1346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        // Untranslatable strings must only exist in the default [empty] locale
1347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (locale.size() > 0) {
1348a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                            SourcePos(in->getPrintableSource(), block.getLineNumber()).warning(
1349a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                                    "string '%s' marked untranslatable but exists in locale '%s'\n",
1350a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                                    String8(name).string(),
1351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    locale.string());
1352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            // hasErrors = localHasErrors = true;
1353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else {
1354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            // Intentionally empty block:
1355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            //
1356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            // Don't add untranslatable strings to the localization table; that
1357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            // way if we later see localizations of them, they'll be flagged as
1358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            // having no default translation.
1359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else {
1361a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                        outTable->addLocalization(
1362a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                                name,
1363a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                                locale,
1364a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                                SourcePos(in->getPrintableSource(), block.getLineNumber()));
1365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (formatted == false16) {
1368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        curIsFormatted = false;
1369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &string16;
1373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = string16;
1374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_STRING;
1375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsStyled = true;
137684410b054c7db0b6685a0f15cb2d1ffcb264f6c9Igor Viarheichyk                curIsPseudolocalizable = fileIsTranslatable && (translatable != false16);
1377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), drawable16.string()) == 0) {
1378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &drawable16;
1379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = drawable16;
1380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_COLOR;
1381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), color16.string()) == 0) {
1382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &color16;
1383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = color16;
1384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_COLOR;
1385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), bool16.string()) == 0) {
1386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &bool16;
1387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = bool16;
1388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_BOOLEAN;
1389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), integer16.string()) == 0) {
1390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &integer16;
1391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = integer16;
1392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_INTEGER;
1393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), dimen16.string()) == 0) {
1394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &dimen16;
1395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = dimen16;
1396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_DIMENSION;
1397282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), fraction16.string()) == 0) {
1398282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &fraction16;
1399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = fraction16;
1400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_FRACTION;
1401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), bag16.string()) == 0) {
1402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &bag16;
1403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsBag = true;
1404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t attri = block.indexOfAttribute(NULL, "type");
1405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (attri >= 0) {
1406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    curType = String16(block.getAttributeStringValue(attri, &len));
1407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            "A 'type' attribute is required for <bag>\n");
1410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), style16.string()) == 0) {
1413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &style16;
1414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = style16;
1415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsBag = true;
1416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), plurals16.string()) == 0) {
1417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &plurals16;
1418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = plurals16;
1419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsBag = true;
1420a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                curIsPseudolocalizable = fileIsTranslatable;
1421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), array16.string()) == 0) {
1422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &array16;
1423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = array16;
1424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsBag = true;
1425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsBagReplaceOnOverwrite = true;
1426282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t formatIdx = block.indexOfAttribute(NULL, "format");
1427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (formatIdx >= 0) {
1428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String16 formatStr = String16(block.getAttributeStringValue(
1429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            formatIdx, &len));
1430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    curFormat = parse_flags(formatStr.string(), formatStr.size(),
1431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                            gFormatFlags);
1432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (curFormat == 0) {
1433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1434282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                "Tag <array> 'format' attribute value \"%s\" not valid\n",
1435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                String8(formatStr).string());
1436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasErrors = localHasErrors = true;
1437282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), string_array16.string()) == 0) {
1440282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Check whether these strings need valid formats.
1441282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // (simplified form of what string16 does above)
1442a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                bool isTranslatable = false;
1443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                size_t n = block.getAttributeCount();
14449a9fa163c384e7fff159d339dfcce3b3122bece5Narayan Kamath
14459a9fa163c384e7fff159d339dfcce3b3122bece5Narayan Kamath                // Pseudolocalizable by default, unless this string array isn't
14469a9fa163c384e7fff159d339dfcce3b3122bece5Narayan Kamath                // translatable.
1447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                for (size_t i = 0; i < n; i++) {
1448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    size_t length;
14494bf58108d442b37ab4adf5ce3a4ecd63472ce254Adam Lesinski                    const char16_t* attr = block.getAttributeName(i, &length);
1450a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                    if (strcmp16(attr, formatted16.string()) == 0) {
14514bf58108d442b37ab4adf5ce3a4ecd63472ce254Adam Lesinski                        const char16_t* value = block.getAttributeStringValue(i, &length);
14529a9fa163c384e7fff159d339dfcce3b3122bece5Narayan Kamath                        if (strcmp16(value, false16.string()) == 0) {
1453a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                            curIsFormatted = false;
14549a9fa163c384e7fff159d339dfcce3b3122bece5Narayan Kamath                        }
1455a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                    } else if (strcmp16(attr, translatable16.string()) == 0) {
14564bf58108d442b37ab4adf5ce3a4ecd63472ce254Adam Lesinski                        const char16_t* value = block.getAttributeStringValue(i, &length);
1457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(value, false16.string()) == 0) {
1458a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                            isTranslatable = false;
1459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &string_array16;
1464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = array16;
1465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_STRING;
1466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsBag = true;
1467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsBagReplaceOnOverwrite = true;
1468a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                curIsPseudolocalizable = isTranslatable && fileIsTranslatable;
1469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), integer_array16.string()) == 0) {
1470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &integer_array16;
1471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = array16;
1472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_INTEGER;
1473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsBag = true;
1474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsBagReplaceOnOverwrite = true;
1475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
1476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "Found tag %s where item is expected\n",
1478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8(block.getElementName(&len)).string());
1479282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return UNKNOWN_ERROR;
1480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String16 ident;
1483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ssize_t identIdx = block.indexOfAttribute(NULL, "name");
1484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (identIdx >= 0) {
1485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ident = String16(block.getAttributeStringValue(identIdx, &len));
1486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
1487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "A 'name' attribute is required for <%s>\n",
1489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8(*curTag).string());
1490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                hasErrors = localHasErrors = true;
1491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String16 product;
1494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            identIdx = block.indexOfAttribute(NULL, "product");
1495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (identIdx >= 0) {
1496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                product = String16(block.getAttributeStringValue(identIdx, &len));
1497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String16 comment(block.getComment(&len) ? block.getComment(&len) : nulStr);
1500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (curIsBag) {
1502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Figure out the parent of this bag...
1503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 parentIdent;
1504282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t parentIdentIdx = block.indexOfAttribute(NULL, "parent");
1505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (parentIdentIdx >= 0) {
1506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    parentIdent = String16(block.getAttributeStringValue(parentIdentIdx, &len));
1507282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1508282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    ssize_t sep = ident.findLast('.');
1509282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (sep >= 0) {
1510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        parentIdent.setTo(ident, sep);
1511282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1512282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1513282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1514282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!localHasErrors) {
1515282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    err = outTable->startBag(SourcePos(in->getPrintableSource(),
1516282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            block.getLineNumber()), myPackage, curType, ident,
1517282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            parentIdent, &curParams,
1518282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            overwrite, curIsBagReplaceOnOverwrite);
1519282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (err != NO_ERROR) {
1520282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasErrors = localHasErrors = true;
1521282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1522282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1523282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1524282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t elmIndex = 0;
1525282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                char elmIndexStr[14];
1526282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                while ((code=block.next()) != ResXMLTree::END_DOCUMENT
1527282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        && code != ResXMLTree::BAD_DOCUMENT) {
1528282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1529282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (code == ResXMLTree::START_TAG) {
1530282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(block.getElementName(&len), item16.string()) != 0) {
1531282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1532282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    "Tag <%s> can not appear inside <%s>, only <item>\n",
1533282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    String8(block.getElementName(&len)).string(),
1534282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    String8(*curTag).string());
1535282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            return UNKNOWN_ERROR;
1536282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1537282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1538282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String16 itemIdent;
1539282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (curType == array16) {
1540282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            sprintf(elmIndexStr, "^index_%d", (int)elmIndex++);
1541282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            itemIdent = String16(elmIndexStr);
1542282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else if (curType == plurals16) {
1543282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            ssize_t itemIdentIdx = block.indexOfAttribute(NULL, "quantity");
1544282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (itemIdentIdx >= 0) {
1545282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                String16 quantity16(block.getAttributeStringValue(itemIdentIdx, &len));
1546282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                if (quantity16 == other16) {
1547282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    itemIdent = quantityOther16;
1548282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                }
1549282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                else if (quantity16 == zero16) {
1550282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    itemIdent = quantityZero16;
1551282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                }
1552282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                else if (quantity16 == one16) {
1553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    itemIdent = quantityOne16;
1554282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                }
1555282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                else if (quantity16 == two16) {
1556282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    itemIdent = quantityTwo16;
1557282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                }
1558282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                else if (quantity16 == few16) {
1559282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    itemIdent = quantityFew16;
1560282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                }
1561282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                else if (quantity16 == many16) {
1562282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    itemIdent = quantityMany16;
1563282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                }
1564282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                else {
1565282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1566282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                            "Illegal 'quantity' attribute is <item> inside <plurals>\n");
1567282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    hasErrors = localHasErrors = true;
1568282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                }
1569282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else {
1570282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1571282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        "A 'quantity' attribute is required for <item> inside <plurals>\n");
1572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasErrors = localHasErrors = true;
1573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else {
1575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            ssize_t itemIdentIdx = block.indexOfAttribute(NULL, "name");
1576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (itemIdentIdx >= 0) {
1577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                itemIdent = String16(block.getAttributeStringValue(itemIdentIdx, &len));
1578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else {
1579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        "A 'name' attribute is required for <item>\n");
1581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasErrors = localHasErrors = true;
1582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ResXMLParser::ResXMLPosition parserPosition;
1586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        block.getPosition(&parserPosition);
1587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        err = parseAndAddBag(bundle, in, &block, curParams, myPackage, curType,
1589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                ident, parentIdent, itemIdent, curFormat, curIsFormatted,
1590a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                product, NO_PSEUDOLOCALIZATION, overwrite, outTable);
1591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (err == NO_ERROR) {
1592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (curIsPseudolocalizable && localeIsDefined(curParams)
1593a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                    && bundle->getPseudolocalize() > 0) {
1594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                // pseudolocalize here
1595a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                if ((PSEUDO_ACCENTED & bundle->getPseudolocalize()) ==
1596a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                   PSEUDO_ACCENTED) {
1597a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                    block.setPosition(parserPosition);
1598a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                    err = parseAndAddBag(bundle, in, &block, pseudoParams, myPackage,
1599a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                            curType, ident, parentIdent, itemIdent, curFormat,
1600a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                            curIsFormatted, product, PSEUDO_ACCENTED,
1601a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                            overwrite, outTable);
1602a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                }
1603a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                if ((PSEUDO_BIDI & bundle->getPseudolocalize()) ==
1604a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                   PSEUDO_BIDI) {
1605a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                    block.setPosition(parserPosition);
1606a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                    err = parseAndAddBag(bundle, in, &block, pseudoBidiParams, myPackage,
1607a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                            curType, ident, parentIdent, itemIdent, curFormat,
1608a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                            curIsFormatted, product, PSEUDO_BIDI,
1609a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                            overwrite, outTable);
1610a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                }
1611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1612a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                        }
1613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (err != NO_ERROR) {
1614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            hasErrors = localHasErrors = true;
1615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (code == ResXMLTree::END_TAG) {
1617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(block.getElementName(&len), curTag->string()) != 0) {
1618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    "Found tag </%s> where </%s> is expected\n",
1620282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    String8(block.getElementName(&len)).string(),
1621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    String8(*curTag).string());
1622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            return UNKNOWN_ERROR;
1623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        break;
1625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1626282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1627282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
1628282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ResXMLParser::ResXMLPosition parserPosition;
1629282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                block.getPosition(&parserPosition);
1630282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1631282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                err = parseAndAddEntry(bundle, in, &block, curParams, myPackage, curType, ident,
1632282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        *curTag, curIsStyled, curFormat, curIsFormatted,
1633a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                        product, NO_PSEUDOLOCALIZATION, overwrite, &skippedResourceNames, outTable);
1634282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (err < NO_ERROR) { // Why err < NO_ERROR instead of err != NO_ERROR?
1636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1637282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                else if (err == NO_ERROR) {
1639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (curIsPseudolocalizable && localeIsDefined(curParams)
1640a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                            && bundle->getPseudolocalize() > 0) {
1641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        // pseudolocalize here
1642a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                        if ((PSEUDO_ACCENTED & bundle->getPseudolocalize()) ==
1643a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                           PSEUDO_ACCENTED) {
1644a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                            block.setPosition(parserPosition);
1645a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                            err = parseAndAddEntry(bundle, in, &block, pseudoParams, myPackage, curType,
1646a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                    ident, *curTag, curIsStyled, curFormat,
1647a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                    curIsFormatted, product,
1648a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                    PSEUDO_ACCENTED, overwrite, &skippedResourceNames, outTable);
1649a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                        }
1650a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                        if ((PSEUDO_BIDI & bundle->getPseudolocalize()) ==
1651a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                           PSEUDO_BIDI) {
1652a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                            block.setPosition(parserPosition);
1653a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                            err = parseAndAddEntry(bundle, in, &block, pseudoBidiParams,
1654a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                    myPackage, curType, ident, *curTag, curIsStyled, curFormat,
1655a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                    curIsFormatted, product,
1656a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                    PSEUDO_BIDI, overwrite, &skippedResourceNames, outTable);
1657a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                        }
1658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (err != NO_ERROR) {
1659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            hasErrors = localHasErrors = true;
1660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#if 0
1666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (comment.size() > 0) {
1667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("Comment for @%s:%s/%s: %s\n", String8(myPackage).string(),
1668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       String8(curType).string(), String8(ident).string(),
1669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       String8(comment).string());
1670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif
1672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!localHasErrors) {
1673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                outTable->appendComment(myPackage, curType, ident, comment, false);
1674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1676282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        else if (code == ResXMLTree::END_TAG) {
1677282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (strcmp16(block.getElementName(&len), resources16.string()) != 0) {
1678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1679282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "Unexpected end tag %s\n", String8(block.getElementName(&len)).string());
1680282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return UNKNOWN_ERROR;
1681282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1682282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1683282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        else if (code == ResXMLTree::START_NAMESPACE || code == ResXMLTree::END_NAMESPACE) {
1684282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1685282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        else if (code == ResXMLTree::TEXT) {
1686282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (isWhitespace(block.getText(&len))) {
1687282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
1688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1690282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    "Found text \"%s\" where item tag is expected\n",
1691282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(block.getText(&len)).string());
1692282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return UNKNOWN_ERROR;
1693282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1694282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
16968ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    // For every resource defined, there must be exist one variant with a product attribute
16978ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    // set to 'default' (or no product attribute at all).
16988ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    // We check to see that for every resource that was ignored because of a mismatched
16998ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    // product attribute, some product variant of that resource was processed.
17008ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    for (size_t i = 0; i < skippedResourceNames.size(); i++) {
17018ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski        if (skippedResourceNames[i]) {
17028ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski            const type_ident_pair_t& p = skippedResourceNames.keyAt(i);
17038ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski            if (!outTable->hasBagOrEntry(myPackage, p.type, p.ident)) {
17048ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                const char* bundleProduct =
17058ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                        (bundle->getProduct() == NULL) ? "" : bundle->getProduct();
17068ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                fprintf(stderr, "In resource file %s: %s\n",
17078ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                        in->getPrintableSource().string(),
17088ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                        curParams.toString().string());
17098ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski
17108ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                fprintf(stderr, "\t%s '%s' does not match product %s.\n"
17118ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                        "\tYou may have forgotten to include a 'default' product variant"
17128ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                        " of the resource.\n",
17138ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                        String8(p.type).string(), String8(p.ident).string(),
17148ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                        bundleProduct[0] == 0 ? "default" : bundleProduct);
17158ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                return UNKNOWN_ERROR;
17168ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski            }
17178ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski        }
17188ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    }
17198ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski
1720282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return hasErrors ? UNKNOWN_ERROR : NO_ERROR;
1721282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1722282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1723833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam LesinskiResourceTable::ResourceTable(Bundle* bundle, const String16& assetsPackage, ResourceTable::PackageType type)
1724833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    : mAssetsPackage(assetsPackage)
1725833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    , mPackageType(type)
1726833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    , mTypeIdOffset(0)
1727833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    , mNumLocal(0)
1728833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    , mBundle(bundle)
1729833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski{
1730833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    ssize_t packageId = -1;
1731833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    switch (mPackageType) {
1732833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        case App:
1733833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        case AppFeature:
1734833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            packageId = 0x7f;
1735833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            break;
1736833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski
1737833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        case System:
1738833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            packageId = 0x01;
1739833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            break;
1740833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski
1741833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        case SharedLibrary:
1742833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            packageId = 0x00;
1743833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            break;
1744833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski
1745833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        default:
1746833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            assert(0);
1747833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            break;
1748833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    }
1749833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    sp<Package> package = new Package(mAssetsPackage, packageId);
1750833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    mPackages.add(assetsPackage, package);
1751833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    mOrderedPackages.add(package);
1752833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski
1753833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    // Every resource table always has one first entry, the bag attributes.
1754833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    const SourcePos unknown(String8("????"), 0);
1755833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    getType(mAssetsPackage, String16("attr"), unknown);
1756833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski}
1757833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski
1758833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinskistatic uint32_t findLargestTypeIdForPackage(const ResTable& table, const String16& packageName) {
1759833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    const size_t basePackageCount = table.getBasePackageCount();
1760833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    for (size_t i = 0; i < basePackageCount; i++) {
1761833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        if (packageName == table.getBasePackageName(i)) {
1762833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            return table.getLastTypeIdForPackage(i);
1763833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        }
1764833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    }
1765833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    return 0;
1766282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1767282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1768282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::addIncludedResources(Bundle* bundle, const sp<AaptAssets>& assets)
1769282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1770282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = assets->buildIncludedResources(bundle);
1771282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
1772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return err;
1773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1774282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mAssets = assets;
1776833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    mTypeIdOffset = findLargestTypeIdForPackage(assets->getIncludedResources(), mAssetsPackage);
1777833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski
1778833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    const String8& featureAfter = bundle->getFeatureAfterPackage();
1779833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    if (!featureAfter.isEmpty()) {
1780833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        AssetManager featureAssetManager;
1781833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        if (!featureAssetManager.addAssetPath(featureAfter, NULL)) {
1782833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            fprintf(stderr, "ERROR: Feature package '%s' not found.\n",
1783833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                    featureAfter.string());
1784833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            return UNKNOWN_ERROR;
1785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1787833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        const ResTable& featureTable = featureAssetManager.getResources(false);
1788833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        mTypeIdOffset = max(mTypeIdOffset,
1789833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                findLargestTypeIdForPackage(featureTable, mAssetsPackage));
1790833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    }
1791282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1792282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
1793282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1794282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1795282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::addPublic(const SourcePos& sourcePos,
1796282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16& package,
1797282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16& type,
1798282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16& name,
1799282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const uint32_t ident)
1800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1801282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t rid = mAssets->getIncludedResources()
1802282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        .identifierForName(name.string(), name.size(),
1803282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           type.string(), type.size(),
1804282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           package.string(), package.size());
1805282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (rid != 0) {
1806282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sourcePos.error("Error declaring public resource %s/%s for included package %s\n",
1807282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String8(type).string(), String8(name).string(),
1808282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String8(package).string());
1809282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
1810282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1811282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1812282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Type> t = getType(package, type, sourcePos);
1813282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (t == NULL) {
1814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
1815282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1816282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return t->addPublic(sourcePos, name, ident);
1817282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1818282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1819282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::addEntry(const SourcePos& sourcePos,
1820282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16& package,
1821282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16& type,
1822282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16& name,
1823282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16& value,
1824282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const Vector<StringPool::entry_style_span>* style,
1825282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const ResTable_config* params,
1826282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const bool doSetIndex,
1827282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const int32_t format,
1828282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const bool overwrite)
1829282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1830282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t rid = mAssets->getIncludedResources()
1831282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        .identifierForName(name.string(), name.size(),
1832282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           type.string(), type.size(),
1833282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           package.string(), package.size());
1834282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (rid != 0) {
1835833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        sourcePos.error("Resource entry %s/%s is already defined in package %s.",
1836833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                String8(type).string(), String8(name).string(), String8(package).string());
1837833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        return UNKNOWN_ERROR;
1838282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1839282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1840282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Entry> e = getEntry(package, type, name, sourcePos, overwrite,
1841282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           params, doSetIndex);
1842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (e == NULL) {
1843282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
1844282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1845282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = e->setItem(sourcePos, value, style, format, overwrite);
1846282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err == NO_ERROR) {
1847282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mNumLocal++;
1848282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1849282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return err;
1850282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1851282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::startBag(const SourcePos& sourcePos,
1853282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16& package,
1854282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16& type,
1855282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16& name,
1856282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16& bagParent,
1857282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const ResTable_config* params,
1858282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 bool overlay,
1859282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 bool replace, bool isId)
1860282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1861282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t result = NO_ERROR;
1862282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1863282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Check for adding entries in other packages...  for now we do
1864282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // nothing.  We need to do the right thing here to support skinning.
1865282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t rid = mAssets->getIncludedResources()
1866282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    .identifierForName(name.string(), name.size(),
1867282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       type.string(), type.size(),
1868282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       package.string(), package.size());
1869282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (rid != 0) {
1870833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        sourcePos.error("Resource entry %s/%s is already defined in package %s.",
1871833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                String8(type).string(), String8(name).string(), String8(package).string());
1872833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        return UNKNOWN_ERROR;
1873282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1874833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski
1875282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (overlay && !mBundle->getAutoAddOverlay() && !hasBagOrEntry(package, type, name)) {
1876282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        bool canAdd = false;
1877282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Package> p = mPackages.valueFor(package);
1878282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (p != NULL) {
1879282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<Type> t = p->getTypes().valueFor(type);
1880282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (t != NULL) {
1881282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (t->getCanAddEntries().indexOf(name) >= 0) {
1882282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    canAdd = true;
1883282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1884282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1885282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1886282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!canAdd) {
1887282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sourcePos.error("Resource does not already exist in overlay at '%s'; use <add-resource> to add.\n",
1888282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            String8(name).string());
1889282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return UNKNOWN_ERROR;
1890282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1891282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1892282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Entry> e = getEntry(package, type, name, sourcePos, overlay, params);
1893282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (e == NULL) {
1894282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
1895282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1896282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1897282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // If a parent is explicitly specified, set it.
1898282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bagParent.size() > 0) {
1899282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        e->setParent(bagParent);
1900282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1901282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1902282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if ((result = e->makeItABag(sourcePos)) != NO_ERROR) {
1903282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return result;
1904282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1905282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1906282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (overlay && replace) {
1907282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return e->emptyBag(sourcePos);
1908282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1909282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return result;
1910282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1911282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1912282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::addBag(const SourcePos& sourcePos,
1913282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                               const String16& package,
1914282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                               const String16& type,
1915282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                               const String16& name,
1916282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                               const String16& bagParent,
1917282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                               const String16& bagKey,
1918282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                               const String16& value,
1919282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                               const Vector<StringPool::entry_style_span>* style,
1920282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                               const ResTable_config* params,
1921282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                               bool replace, bool isId, const int32_t format)
1922282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1923282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Check for adding entries in other packages...  for now we do
1924282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // nothing.  We need to do the right thing here to support skinning.
1925282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t rid = mAssets->getIncludedResources()
1926282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        .identifierForName(name.string(), name.size(),
1927282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           type.string(), type.size(),
1928282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           package.string(), package.size());
1929282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (rid != 0) {
1930282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NO_ERROR;
1931282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1932282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1933282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#if 0
1934282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (name == String16("left")) {
1935282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printf("Adding bag left: file=%s, line=%d, type=%s\n",
1936282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski               sourcePos.file.striing(), sourcePos.line, String8(type).string());
1937282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1938282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif
1939282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Entry> e = getEntry(package, type, name, sourcePos, replace, params);
1940282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (e == NULL) {
1941282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
1942282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1943282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1944282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // If a parent is explicitly specified, set it.
1945282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bagParent.size() > 0) {
1946282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        e->setParent(bagParent);
1947282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1948282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1949282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const bool first = e->getBag().indexOfKey(bagKey) < 0;
1950282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = e->addToBag(sourcePos, bagKey, value, style, replace, isId, format);
1951282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err == NO_ERROR && first) {
1952282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mNumLocal++;
1953282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1954282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return err;
1955282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1956282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1957282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::hasBagOrEntry(const String16& package,
1958282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16& type,
1959282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16& name) const
1960282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1961282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // First look for this in the included resources...
1962282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t rid = mAssets->getIncludedResources()
1963282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        .identifierForName(name.string(), name.size(),
1964282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           type.string(), type.size(),
1965282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           package.string(), package.size());
1966282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (rid != 0) {
1967282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
1968282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1969282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1970282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Package> p = mPackages.valueFor(package);
1971282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (p != NULL) {
1972282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Type> t = p->getTypes().valueFor(type);
1973282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (t != NULL) {
1974282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<ConfigList> c =  t->getConfigs().valueFor(name);
1975282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (c != NULL) return true;
1976282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1977282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1978282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1979282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
1980282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1981282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1982282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::hasBagOrEntry(const String16& package,
1983282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16& type,
1984282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16& name,
1985282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const ResTable_config& config) const
1986282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1987282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // First look for this in the included resources...
1988282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t rid = mAssets->getIncludedResources()
1989282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        .identifierForName(name.string(), name.size(),
1990282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           type.string(), type.size(),
1991282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           package.string(), package.size());
1992282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (rid != 0) {
1993282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
1994282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1995282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1996282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Package> p = mPackages.valueFor(package);
1997282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (p != NULL) {
1998282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Type> t = p->getTypes().valueFor(type);
1999282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (t != NULL) {
2000282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<ConfigList> c =  t->getConfigs().valueFor(name);
2001282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (c != NULL) {
2002282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<Entry> e = c->getEntries().valueFor(config);
2003282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (e != NULL) {
2004282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return true;
2005282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2006282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2007282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2008282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2009282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2010282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
2011282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2012282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2013282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::hasBagOrEntry(const String16& ref,
2014282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16* defType,
2015282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16* defPackage)
2016282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2017282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String16 package, type, name;
2018282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (!ResTable::expandResourceRef(ref.string(), ref.size(), &package, &type, &name,
2019282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                defType, defPackage ? defPackage:&mAssetsPackage, NULL)) {
2020282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return false;
2021282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2022282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return hasBagOrEntry(package, type, name);
2023282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2024282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2025282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::appendComment(const String16& package,
2026282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16& type,
2027282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16& name,
2028282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16& comment,
2029282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  bool onlyIfEmpty)
2030282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2031282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (comment.size() <= 0) {
2032282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
2033282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2034282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2035282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Package> p = mPackages.valueFor(package);
2036282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (p != NULL) {
2037282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Type> t = p->getTypes().valueFor(type);
2038282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (t != NULL) {
2039282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<ConfigList> c =  t->getConfigs().valueFor(name);
2040282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (c != NULL) {
2041282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                c->appendComment(comment, onlyIfEmpty);
2042282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return true;
2043282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2044282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2045282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2046282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
2047282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2048282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2049282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::appendTypeComment(const String16& package,
2050282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                      const String16& type,
2051282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                      const String16& name,
2052282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                      const String16& comment)
2053282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2054282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (comment.size() <= 0) {
2055282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
2056282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2057282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2058282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Package> p = mPackages.valueFor(package);
2059282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (p != NULL) {
2060282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Type> t = p->getTypes().valueFor(type);
2061282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (t != NULL) {
2062282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<ConfigList> c =  t->getConfigs().valueFor(name);
2063282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (c != NULL) {
2064282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                c->appendTypeComment(comment);
2065282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return true;
2066282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2067282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2068282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2069282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
2070282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2071282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2072282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid ResourceTable::canAddEntry(const SourcePos& pos,
2073282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String16& package, const String16& type, const String16& name)
2074282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2075282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Type> t = getType(package, type, pos);
2076282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (t != NULL) {
2077282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        t->canAddEntry(name);
2078282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2079282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2080282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2081282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisize_t ResourceTable::size() const {
2082282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return mPackages.size();
2083282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2084282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2085282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisize_t ResourceTable::numLocalResources() const {
2086282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return mNumLocal;
2087282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2088282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2089282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::hasResources() const {
2090282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return mNumLocal > 0;
2091282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2092282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
209327f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinskisp<AaptFile> ResourceTable::flatten(Bundle* bundle, const sp<const ResourceFilter>& filter,
209427f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski        const bool isBase)
2095282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2096282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<AaptFile> data = new AaptFile(String8(), AaptGroupEntry(), String8());
209727f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski    status_t err = flatten(bundle, filter, data, isBase);
2098282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return err == NO_ERROR ? data : NULL;
2099282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiinline uint32_t ResourceTable::getResId(const sp<Package>& p,
2102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        const sp<Type>& t,
2103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        uint32_t nameId)
2104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return makeResId(p->getAssignedId(), t->getIndex(), nameId);
2106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiuint32_t ResourceTable::getResId(const String16& package,
2109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16& type,
2110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16& name,
2111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 bool onlyPublic) const
2112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t id = ResourceIdCache::lookup(package, type, name, onlyPublic);
2114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (id != 0) return id;     // cache hit
2115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // First look for this in the included resources...
2117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t specFlags = 0;
2118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t rid = mAssets->getIncludedResources()
2119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        .identifierForName(name.string(), name.size(),
2120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           type.string(), type.size(),
2121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           package.string(), package.size(),
2122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           &specFlags);
2123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (rid != 0) {
2124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (onlyPublic) {
2125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if ((specFlags & ResTable_typeSpec::SPEC_PUBLIC) == 0) {
2126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return 0;
2127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2130833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        return ResourceIdCache::store(package, type, name, onlyPublic, rid);
2131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2133833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    sp<Package> p = mPackages.valueFor(package);
2134833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    if (p == NULL) return 0;
2135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Type> t = p->getTypes().valueFor(type);
2136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (t == NULL) return 0;
21379b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski    sp<ConfigList> c = t->getConfigs().valueFor(name);
21389b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski    if (c == NULL) {
21399b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski        if (type != String16("attr")) {
21409b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski            return 0;
21419b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski        }
21429b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski        t = p->getTypes().valueFor(String16(kAttrPrivateType));
21439b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski        if (t == NULL) return 0;
21449b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski        c = t->getConfigs().valueFor(name);
21459b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski        if (c == NULL) return 0;
21469b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski    }
2147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int32_t ei = c->getEntryIndex();
2148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (ei < 0) return 0;
2149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return ResourceIdCache::store(package, type, name, onlyPublic,
2151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            getResId(p, t, ei));
2152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiuint32_t ResourceTable::getResId(const String16& ref,
2155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16* defType,
2156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16* defPackage,
2157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const char** outErrorMsg,
2158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 bool onlyPublic) const
2159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String16 package, type, name;
2161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool refOnlyPublic = true;
2162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (!ResTable::expandResourceRef(
2163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ref.string(), ref.size(), &package, &type, &name,
2164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        defType, defPackage ? defPackage:&mAssetsPackage,
2165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        outErrorMsg, &refOnlyPublic)) {
2166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        NOISY(printf("Expanding resource: ref=%s\n",
2167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                     String8(ref).string()));
2168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        NOISY(printf("Expanding resource: defType=%s\n",
2169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                     defType ? String8(*defType).string() : "NULL"));
2170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        NOISY(printf("Expanding resource: defPackage=%s\n",
2171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                     defPackage ? String8(*defPackage).string() : "NULL"));
2172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        NOISY(printf("Expanding resource: ref=%s\n", String8(ref).string()));
2173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        NOISY(printf("Expanded resource: p=%s, t=%s, n=%s, res=0\n",
2174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                     String8(package).string(), String8(type).string(),
2175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                     String8(name).string()));
2176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return 0;
2177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t res = getResId(package, type, name, onlyPublic && refOnlyPublic);
2179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    NOISY(printf("Expanded resource: p=%s, t=%s, n=%s, res=%d\n",
2180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 String8(package).string(), String8(type).string(),
2181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 String8(name).string(), res));
2182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (res == 0) {
2183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (outErrorMsg)
2184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            *outErrorMsg = "No resource found that matches the given name";
2185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return res;
2187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::isValidResourceName(const String16& s)
2190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char16_t* p = s.string();
2192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool first = true;
2193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (*p) {
2194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if ((*p >= 'a' && *p <= 'z')
2195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            || (*p >= 'A' && *p <= 'Z')
2196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            || *p == '_'
2197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            || (!first && *p >= '0' && *p <= '9')) {
2198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            first = false;
2199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            p++;
2200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
2201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return false;
2203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return true;
2205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::stringToValue(Res_value* outValue, StringPool* pool,
2208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16& str,
2209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  bool preserveSpaces, bool coerceType,
2210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  uint32_t attrID,
2211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const Vector<StringPool::entry_style_span>* style,
2212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  String16* outStr, void* accessorCookie,
2213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  uint32_t attrType, const String8* configTypeName,
2214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const ConfigDescription* config)
2215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String16 finalStr;
2217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool res = true;
2219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (style == NULL || style->size() == 0) {
2220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Text is not styled so it can be any type...  let's figure it out.
2221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        res = mAssets->getIncludedResources()
2222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            .stringToValue(outValue, &finalStr, str.string(), str.size(), preserveSpaces,
2223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            coerceType, attrID, NULL, &mAssetsPackage, this,
2224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           accessorCookie, attrType);
2225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
2226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Styled text can only be a string, and while collecting the style
2227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // information we have already processed that string!
2228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        outValue->size = sizeof(Res_value);
2229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        outValue->res0 = 0;
2230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        outValue->dataType = outValue->TYPE_STRING;
2231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        outValue->data = 0;
2232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        finalStr = str;
2233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (!res) {
2236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return false;
2237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (outValue->dataType == outValue->TYPE_STRING) {
2240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Should do better merging styles.
2241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (pool) {
2242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 configStr;
2243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (config != NULL) {
2244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                configStr = config->toString();
2245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
2246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                configStr = "(null)";
2247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            NOISY(printf("Adding to pool string style #%d config %s: %s\n",
2249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    style != NULL ? style->size() : 0,
2250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    configStr.string(), String8(finalStr).string()));
2251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (style != NULL && style->size() > 0) {
2252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                outValue->data = pool->add(finalStr, *style, configTypeName, config);
2253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
2254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                outValue->data = pool->add(finalStr, true, configTypeName, config);
2255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
2257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Caller will fill this in later.
2258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            outValue->data = 0;
2259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (outStr) {
2262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            *outStr = finalStr;
2263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return true;
2268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiuint32_t ResourceTable::getCustomResource(
2271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16& package, const String16& type, const String16& name) const
2272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //printf("getCustomResource: %s %s %s\n", String8(package).string(),
2274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //       String8(type).string(), String8(name).string());
2275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Package> p = mPackages.valueFor(package);
2276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (p == NULL) return 0;
2277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Type> t = p->getTypes().valueFor(type);
2278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (t == NULL) return 0;
2279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<ConfigList> c =  t->getConfigs().valueFor(name);
22809b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski    if (c == NULL) {
22819b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski        if (type != String16("attr")) {
22829b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski            return 0;
22839b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski        }
22849b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski        t = p->getTypes().valueFor(String16(kAttrPrivateType));
22859b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski        if (t == NULL) return 0;
22869b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski        c = t->getConfigs().valueFor(name);
22879b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski        if (c == NULL) return 0;
22889b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski    }
2289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int32_t ei = c->getEntryIndex();
2290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (ei < 0) return 0;
2291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return getResId(p, t, ei);
2292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiuint32_t ResourceTable::getCustomResourceWithCreation(
2295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String16& package, const String16& type, const String16& name,
2296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const bool createIfNotFound)
2297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t resId = getCustomResource(package, type, name);
2299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (resId != 0 || !createIfNotFound) {
2300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return resId;
2301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2303f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski    if (mAssetsPackage != package) {
2304833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        mCurrentXmlPos.error("creating resource for external package %s: %s/%s.",
2305f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                String8(package).string(), String8(type).string(), String8(name).string());
2306833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        if (package == String16("android")) {
2307833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            mCurrentXmlPos.printf("did you mean to use @+id instead of @+android:id?");
2308833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        }
2309833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        return 0;
2310f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski    }
2311f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski
2312f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski    String16 value("false");
2313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t status = addEntry(mCurrentXmlPos, package, type, name, value, NULL, NULL, true);
2314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (status == NO_ERROR) {
2315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        resId = getResId(package, type, name);
2316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return resId;
2317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return 0;
2319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiuint32_t ResourceTable::getRemappedPackage(uint32_t origPackage) const
2322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return origPackage;
2324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::getAttributeType(uint32_t attrID, uint32_t* outType)
2327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //printf("getAttributeType #%08x\n", attrID);
2329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Res_value value;
2330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (getItemValue(attrID, ResTable_map::ATTR_TYPE, &value)) {
2331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //printf("getAttributeType #%08x (%s): #%08x\n", attrID,
2332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //       String8(getEntry(attrID)->getName()).string(), value.data);
2333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        *outType = value.data;
2334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
2335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
2337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::getAttributeMin(uint32_t attrID, uint32_t* outMin)
2340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //printf("getAttributeMin #%08x\n", attrID);
2342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Res_value value;
2343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (getItemValue(attrID, ResTable_map::ATTR_MIN, &value)) {
2344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        *outMin = value.data;
2345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
2346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
2348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::getAttributeMax(uint32_t attrID, uint32_t* outMax)
2351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //printf("getAttributeMax #%08x\n", attrID);
2353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Res_value value;
2354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (getItemValue(attrID, ResTable_map::ATTR_MAX, &value)) {
2355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        *outMax = value.data;
2356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
2357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
2359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiuint32_t ResourceTable::getAttributeL10N(uint32_t attrID)
2362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //printf("getAttributeL10N #%08x\n", attrID);
2364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Res_value value;
2365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (getItemValue(attrID, ResTable_map::ATTR_L10N, &value)) {
2366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return value.data;
2367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return ResTable_map::L10N_NOT_REQUIRED;
2369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::getLocalizationSetting()
2372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return mBundle->getRequireLocalization();
2374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid ResourceTable::reportError(void* accessorCookie, const char* fmt, ...)
2377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (accessorCookie != NULL && fmt != NULL) {
2379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        AccessorCookie* ac = (AccessorCookie*)accessorCookie;
2380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int retval=0;
2381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        char buf[1024];
2382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        va_list ap;
2383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        va_start(ap, fmt);
2384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        retval = vsnprintf(buf, sizeof(buf), fmt, ap);
2385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        va_end(ap);
2386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ac->sourcePos.error("Error: %s (at '%s' with value '%s').\n",
2387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            buf, ac->attr.string(), ac->value.string());
2388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::getAttributeKeys(
2392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t attrID, Vector<String16>* outKeys)
2393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<const Entry> e = getEntry(attrID);
2395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (e != NULL) {
2396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t N = e->getBag().size();
2397282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (size_t i=0; i<N; i++) {
2398282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const String16& key = e->getBag().keyAt(i);
2399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (key.size() > 0 && key.string()[0] != '^') {
2400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                outKeys->add(key);
2401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
2404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
2406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::getAttributeEnum(
2409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t attrID, const char16_t* name, size_t nameLen,
2410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Res_value* outValue)
2411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //printf("getAttributeEnum #%08x %s\n", attrID, String8(name, nameLen).string());
2413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String16 nameStr(name, nameLen);
2414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<const Entry> e = getEntry(attrID);
2415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (e != NULL) {
2416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t N = e->getBag().size();
2417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (size_t i=0; i<N; i++) {
2418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //printf("Comparing %s to %s\n", String8(name, nameLen).string(),
2419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //       String8(e->getBag().keyAt(i)).string());
2420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (e->getBag().keyAt(i) == nameStr) {
2421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return getItemValue(attrID, e->getBag().valueAt(i).bagKeyId, outValue);
2422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
2426282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::getAttributeFlags(
2429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t attrID, const char16_t* name, size_t nameLen,
2430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Res_value* outValue)
2431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    outValue->dataType = Res_value::TYPE_INT_HEX;
2433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    outValue->data = 0;
2434282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //printf("getAttributeFlags #%08x %s\n", attrID, String8(name, nameLen).string());
2436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String16 nameStr(name, nameLen);
2437282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<const Entry> e = getEntry(attrID);
2438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (e != NULL) {
2439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t N = e->getBag().size();
2440282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2441282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const char16_t* end = name + nameLen;
2442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const char16_t* pos = name;
2443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        while (pos < end) {
2444282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const char16_t* start = pos;
2445282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            while (pos < end && *pos != '|') {
2446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                pos++;
2447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String16 nameStr(start, pos-start);
2450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            size_t i;
2451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (i=0; i<N; i++) {
2452282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                //printf("Comparing \"%s\" to \"%s\"\n", String8(nameStr).string(),
2453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                //       String8(e->getBag().keyAt(i)).string());
2454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (e->getBag().keyAt(i) == nameStr) {
2455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    Res_value val;
2456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    bool got = getItemValue(attrID, e->getBag().valueAt(i).bagKeyId, &val);
2457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (!got) {
2458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        return false;
2459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    //printf("Got value: 0x%08x\n", val.data);
2461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    outValue->data |= val.data;
2462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    break;
2463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (i >= N) {
2467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Didn't find this flag identifier.
2468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return false;
2469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            pos++;
2471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
2474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
2476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::assignResourceIds()
2479282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t N = mOrderedPackages.size();
2481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t pi;
2482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t firstError = NO_ERROR;
2483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // First generate all bag attributes and assign indices.
2485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (pi=0; pi<N; pi++) {
2486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Package> p = mOrderedPackages.itemAt(pi);
2487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (p == NULL || p->getTypes().size() == 0) {
2488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Empty, skip!
2489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
2490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
24929b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski        if (mPackageType == System) {
24939b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski            p->movePrivateAttrs();
24949b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski        }
24959b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski
2496833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        // This has no sense for packages being built as AppFeature (aka with a non-zero offset).
2497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        status_t err = p->applyPublicTypeOrder();
2498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != NO_ERROR && firstError == NO_ERROR) {
2499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            firstError = err;
2500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Generate attributes...
2503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t N = p->getOrderedTypes().size();
2504282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        size_t ti;
2505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (ti=0; ti<N; ti++) {
2506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<Type> t = p->getOrderedTypes().itemAt(ti);
2507282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (t == NULL) {
2508282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
2509282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t N = t->getOrderedConfigs().size();
2511282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t ci=0; ci<N; ci++) {
2512282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<ConfigList> c = t->getOrderedConfigs().itemAt(ci);
2513282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (c == NULL) {
2514282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
2515282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2516282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                const size_t N = c->getEntries().size();
2517282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                for (size_t ei=0; ei<N; ei++) {
2518282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sp<Entry> e = c->getEntries().valueAt(ei);
2519282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (e == NULL) {
2520282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        continue;
2521282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2522282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    status_t err = e->generateAttributes(this, p->getName());
2523282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (err != NO_ERROR && firstError == NO_ERROR) {
2524282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        firstError = err;
2525282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2526282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2527282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2528282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2529282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2530833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        uint32_t typeIdOffset = 0;
2531833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        if (mPackageType == AppFeature && p->getName() == mAssetsPackage) {
2532833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            typeIdOffset = mTypeIdOffset;
2533833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        }
2534833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski
2535282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const SourcePos unknown(String8("????"), 0);
2536282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Type> attr = p->getType(String16("attr"), unknown);
2537282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2538282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Assign indices...
253943a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski        const size_t typeCount = p->getOrderedTypes().size();
254043a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski        for (size_t ti = 0; ti < typeCount; ti++) {
2541282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<Type> t = p->getOrderedTypes().itemAt(ti);
2542282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (t == NULL) {
2543282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
2544282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
254543a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski
2546282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            err = t->applyPublicEntryOrder();
2547282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (err != NO_ERROR && firstError == NO_ERROR) {
2548282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                firstError = err;
2549282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2550282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2551282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t N = t->getOrderedConfigs().size();
2552833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            t->setIndex(ti + 1 + typeIdOffset);
2553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2554282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            LOG_ALWAYS_FATAL_IF(ti == 0 && attr != t,
2555282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                "First type is not attr!");
2556282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2557282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t ei=0; ei<N; ei++) {
2558282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<ConfigList> c = t->getOrderedConfigs().itemAt(ei);
2559282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (c == NULL) {
2560282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
2561282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2562282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                c->setEntryIndex(ei);
2563282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2564282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2565282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
25669b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski
2567282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Assign resource IDs to keys in bags...
256843a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski        for (size_t ti = 0; ti < typeCount; ti++) {
2569282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<Type> t = p->getOrderedTypes().itemAt(ti);
2570282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (t == NULL) {
2571282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
2572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
25739b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski
2574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t N = t->getOrderedConfigs().size();
2575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t ci=0; ci<N; ci++) {
2576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<ConfigList> c = t->getOrderedConfigs().itemAt(ci);
25779b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski                if (c == NULL) {
25789b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski                    continue;
25799b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski                }
2580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                //printf("Ordered config #%d: %p\n", ci, c.get());
2581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                const size_t N = c->getEntries().size();
2582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                for (size_t ei=0; ei<N; ei++) {
2583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sp<Entry> e = c->getEntries().valueAt(ei);
2584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (e == NULL) {
2585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        continue;
2586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    status_t err = e->assignResourceIds(this, p->getName());
2588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (err != NO_ERROR && firstError == NO_ERROR) {
2589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        firstError = err;
2590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2593282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return firstError;
2596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::addSymbols(const sp<AaptSymbols>& outSymbols) {
2599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t N = mOrderedPackages.size();
2600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t pi;
2601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (pi=0; pi<N; pi++) {
2603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Package> p = mOrderedPackages.itemAt(pi);
2604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (p->getTypes().size() == 0) {
2605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Empty, skip!
2606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
2607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t N = p->getOrderedTypes().size();
2610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        size_t ti;
2611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (ti=0; ti<N; ti++) {
2613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<Type> t = p->getOrderedTypes().itemAt(ti);
2614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (t == NULL) {
2615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
2616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
26179b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski
2618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t N = t->getOrderedConfigs().size();
26199b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski            sp<AaptSymbols> typeSymbols;
26209b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski            if (t->getName() == String16(kAttrPrivateType)) {
26219b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski                typeSymbols = outSymbols->addNestedSymbol(String8("attr"), t->getPos());
26229b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski            } else {
26239b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski                typeSymbols = outSymbols->addNestedSymbol(String8(t->getName()), t->getPos());
26249b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski            }
26259b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski
26263fb8c9b50ef1873454acf3a4e7fd33ad182c03d7Adam Lesinski            if (typeSymbols == NULL) {
26273fb8c9b50ef1873454acf3a4e7fd33ad182c03d7Adam Lesinski                return UNKNOWN_ERROR;
26283fb8c9b50ef1873454acf3a4e7fd33ad182c03d7Adam Lesinski            }
26293fb8c9b50ef1873454acf3a4e7fd33ad182c03d7Adam Lesinski
2630282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t ci=0; ci<N; ci++) {
2631282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<ConfigList> c = t->getOrderedConfigs().itemAt(ci);
2632282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (c == NULL) {
2633282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
2634282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                uint32_t rid = getResId(p, t, ci);
2636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (rid == 0) {
2637282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return UNKNOWN_ERROR;
2638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2639833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                if (Res_GETPACKAGE(rid) + 1 == p->getAssignedId()) {
2640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    typeSymbols->addSymbol(String8(c->getName()), rid, c->getPos());
2641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String16 comment(c->getComment());
2643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    typeSymbols->appendComment(String8(c->getName()), comment, c->getPos());
26448ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                    //printf("Type symbol [%08x] %s comment: %s\n", rid,
26458ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                    //        String8(c->getName()).string(), String8(comment).string());
2646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    comment = c->getTypeComment();
2647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    typeSymbols->appendTypeComment(String8(c->getName()), comment);
2648282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
2653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid
2657a01a9374fd386f3a8773528d7a49bc5315492dffAdam LesinskiResourceTable::addLocalization(const String16& name, const String8& locale, const SourcePos& src)
2658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2659a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski    mLocalizations[name][locale] = src;
2660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*!
2664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Flag various sorts of localization problems.  '+' indicates checks already implemented;
2665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * '-' indicates checks that will be implemented in the future.
2666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
2667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * + A localized string for which no default-locale version exists => warning
2668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * + A string for which no version in an explicitly-requested locale exists => warning
2669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * + A localized translation of an translateable="false" string => warning
2670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * - A localized string not provided in every locale used by the table
2671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
2672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t
2673282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiResourceTable::validateLocalizations(void)
2674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = NO_ERROR;
2676282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String8 defaultLocale;
2677282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // For all strings...
2679a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski    for (map<String16, map<String8, SourcePos> >::iterator nameIter = mLocalizations.begin();
2680282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         nameIter != mLocalizations.end();
2681282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         nameIter++) {
2682a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski        const map<String8, SourcePos>& configSrcMap = nameIter->second;
2683282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2684282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Look for strings with no default localization
2685a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski        if (configSrcMap.count(defaultLocale) == 0) {
2686a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski            SourcePos().warning("string '%s' has no default translation.",
2687a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                    String8(nameIter->first).string());
2688a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski            if (mBundle->getVerbose()) {
2689a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                for (map<String8, SourcePos>::const_iterator locales = configSrcMap.begin();
2690a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                    locales != configSrcMap.end();
2691a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                    locales++) {
2692a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                    locales->second.printf("locale %s found", locales->first.string());
2693a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                }
2694282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // !!! TODO: throw an error here in some circumstances
2696282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Check that all requested localizations are present for this string
2699fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        if (mBundle->getConfigurations().size() > 0 && mBundle->getRequireLocalization()) {
2700fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            const char* allConfigs = mBundle->getConfigurations().string();
2701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const char* start = allConfigs;
2702282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const char* comma;
2703282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2704a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski            set<String8> missingConfigs;
2705a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski            AaptLocaleValue locale;
2706282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            do {
2707282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String8 config;
2708282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                comma = strchr(start, ',');
2709282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (comma != NULL) {
2710282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    config.setTo(start, comma - start);
2711282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    start = comma + 1;
2712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
2713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    config.setTo(start);
2714282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2716a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                if (!locale.initFromFilterString(config)) {
2717a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                    continue;
2718a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                }
2719a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski
2720a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                // don't bother with the pseudolocale "en_XA" or "ar_XB"
2721a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                if (config != "en_XA" && config != "ar_XB") {
2722a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                    if (configSrcMap.find(config) == configSrcMap.end()) {
2723282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        // okay, no specific localization found.  it's possible that we are
2724282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        // requiring a specific regional localization [e.g. de_DE] but there is an
2725282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        // available string in the generic language localization [e.g. de];
2726282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        // consider that string to have fulfilled the localization requirement.
2727282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8 region(config.string(), 2);
2728a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                        if (configSrcMap.find(region) == configSrcMap.end() &&
2729a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                                configSrcMap.count(defaultLocale) == 0) {
2730a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                            missingConfigs.insert(config);
2731282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
2732282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2733282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2734a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski            } while (comma != NULL);
2735a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski
2736a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski            if (!missingConfigs.empty()) {
2737a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                String8 configStr;
2738a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                for (set<String8>::iterator iter = missingConfigs.begin();
2739a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                     iter != missingConfigs.end();
2740a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                     iter++) {
2741a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                    configStr.appendFormat(" %s", iter->string());
2742a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                }
2743a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                SourcePos().warning("string '%s' is missing %u required localizations:%s",
2744a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                        String8(nameIter->first).string(),
2745a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                        (unsigned int)missingConfigs.size(),
2746a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                        configStr.string());
2747a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski            }
2748282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2749282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2751282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return err;
2752282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2753282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
275427f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinskistatus_t ResourceTable::flatten(Bundle* bundle, const sp<const ResourceFilter>& filter,
275527f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski        const sp<AaptFile>& dest,
275627f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski        const bool isBase)
2757282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2758282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const ConfigDescription nullConfig;
2759282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2760282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t N = mOrderedPackages.size();
2761282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t pi;
2762282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2763282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const static String16 mipmap16("mipmap");
2764282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2765282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool useUTF8 = !bundle->getUTF16StringsOption();
2766282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2767de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski    // The libraries this table references.
2768de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski    Vector<sp<Package> > libraryPackages;
27696022debdbcc4498736580640c6287b57872617a2Adam Lesinski    const ResTable& table = mAssets->getIncludedResources();
27706022debdbcc4498736580640c6287b57872617a2Adam Lesinski    const size_t basePackageCount = table.getBasePackageCount();
27716022debdbcc4498736580640c6287b57872617a2Adam Lesinski    for (size_t i = 0; i < basePackageCount; i++) {
27726022debdbcc4498736580640c6287b57872617a2Adam Lesinski        size_t packageId = table.getBasePackageId(i);
27736022debdbcc4498736580640c6287b57872617a2Adam Lesinski        String16 packageName(table.getBasePackageName(i));
27746022debdbcc4498736580640c6287b57872617a2Adam Lesinski        if (packageId > 0x01 && packageId != 0x7f &&
27756022debdbcc4498736580640c6287b57872617a2Adam Lesinski                packageName != String16("android")) {
27766022debdbcc4498736580640c6287b57872617a2Adam Lesinski            libraryPackages.add(sp<Package>(new Package(packageName, packageId)));
27776022debdbcc4498736580640c6287b57872617a2Adam Lesinski        }
27786022debdbcc4498736580640c6287b57872617a2Adam Lesinski    }
2779de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski
2780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Iterate through all data, collecting all values (strings,
2781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // references, etc).
2782282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    StringPool valueStrings(useUTF8);
2783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Vector<sp<Entry> > allEntries;
2784282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (pi=0; pi<N; pi++) {
2785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Package> p = mOrderedPackages.itemAt(pi);
2786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (p->getTypes().size() == 0) {
2787282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
2788282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2789282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2790282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        StringPool typeStrings(useUTF8);
2791282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        StringPool keyStrings(useUTF8);
2792282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2793833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        ssize_t stringsAdded = 0;
2794282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t N = p->getOrderedTypes().size();
2795282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (size_t ti=0; ti<N; ti++) {
2796282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<Type> t = p->getOrderedTypes().itemAt(ti);
2797282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (t == NULL) {
2798282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                typeStrings.add(String16("<empty>"), false);
2799833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                stringsAdded++;
2800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
2801282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2802833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski
2803833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            while (stringsAdded < t->getIndex() - 1) {
2804833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                typeStrings.add(String16("<empty>"), false);
2805833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                stringsAdded++;
2806833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            }
2807833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski
2808282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const String16 typeName(t->getName());
2809282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            typeStrings.add(typeName, false);
2810833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            stringsAdded++;
2811282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2812282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // This is a hack to tweak the sorting order of the final strings,
2813282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // to put stuff that is generally not language-specific first.
2814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 configTypeName(typeName);
2815282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (configTypeName == "drawable" || configTypeName == "layout"
2816282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    || configTypeName == "color" || configTypeName == "anim"
2817282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    || configTypeName == "interpolator" || configTypeName == "animator"
2818282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    || configTypeName == "xml" || configTypeName == "menu"
2819282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    || configTypeName == "mipmap" || configTypeName == "raw") {
2820282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                configTypeName = "1complex";
2821282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
2822282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                configTypeName = "2value";
2823282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2824282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
282527f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski            // mipmaps don't get filtered, so they will
282627f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski            // allways end up in the base. Make sure they
282727f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski            // don't end up in a split.
282827f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski            if (typeName == mipmap16 && !isBase) {
282927f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski                continue;
283027f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski            }
283127f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski
2832282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const bool filterable = (typeName != mipmap16);
2833282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2834282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t N = t->getOrderedConfigs().size();
2835282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t ci=0; ci<N; ci++) {
2836282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<ConfigList> c = t->getOrderedConfigs().itemAt(ci);
2837282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (c == NULL) {
2838282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
2839282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2840282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                const size_t N = c->getEntries().size();
2841282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                for (size_t ei=0; ei<N; ei++) {
2842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    ConfigDescription config = c->getEntries().keyAt(ei);
2843fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    if (filterable && !filter->match(config)) {
2844282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        continue;
2845282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2846282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sp<Entry> e = c->getEntries().valueAt(ei);
2847282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (e == NULL) {
2848282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        continue;
2849282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2850282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    e->setNameIndex(keyStrings.add(e->getName(), true));
2851282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // If this entry has no values for other configs,
2853282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // and is the default config, then it is special.  Otherwise
2854282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // we want to add it with the config info.
2855282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    ConfigDescription* valueConfig = NULL;
2856282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (N != 1 || config == nullConfig) {
2857282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        valueConfig = &config;
2858282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2859282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2860282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    status_t err = e->prepareFlatten(&valueStrings, this,
2861282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            &configTypeName, &config);
2862282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (err != NO_ERROR) {
2863282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        return err;
2864282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2865282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    allEntries.add(e);
2866282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2867282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2868282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2869282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2870282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        p->setTypeStrings(typeStrings.createStringBlock());
2871282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        p->setKeyStrings(keyStrings.createStringBlock());
2872282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2873282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2874282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getOutputAPKFile() != NULL) {
2875282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Now we want to sort the value strings for better locality.  This will
2876282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // cause the positions of the strings to change, so we need to go back
2877282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // through out resource entries and update them accordingly.  Only need
2878282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // to do this if actually writing the output file.
2879282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        valueStrings.sortByConfig();
2880282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (pi=0; pi<allEntries.size(); pi++) {
2881282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            allEntries[pi]->remapStringValue(&valueStrings);
2882282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2883282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2884282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2885282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t strAmt = 0;
2886de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski
2887282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Now build the array of package chunks.
2888282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Vector<sp<AaptFile> > flatPackages;
2889282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (pi=0; pi<N; pi++) {
2890282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Package> p = mOrderedPackages.itemAt(pi);
2891282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (p->getTypes().size() == 0) {
2892282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Empty, skip!
2893282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
2894282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2895282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2896282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t N = p->getTypeStrings().size();
2897282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2898282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t baseSize = sizeof(ResTable_package);
2899282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2900282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Start the package data.
2901282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<AaptFile> data = new AaptFile(String8(), AaptGroupEntry(), String8());
2902282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ResTable_package* header = (ResTable_package*)data->editData(baseSize);
2903282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (header == NULL) {
2904282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: out of memory creating ResTable_package\n");
2905282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return NO_MEMORY;
2906282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2907282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        memset(header, 0, sizeof(*header));
2908282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header->header.type = htods(RES_TABLE_PACKAGE_TYPE);
2909282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header->header.headerSize = htods(sizeof(*header));
2910833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        header->id = htodl(static_cast<uint32_t>(p->getAssignedId()));
2911282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        strcpy16_htod(header->name, p->getName().string());
2912282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2913282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Write the string blocks.
2914282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t typeStringsStart = data->getSize();
2915282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<AaptFile> strFile = p->getTypeStringsData();
2916282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ssize_t amt = data->writeData(strFile->getData(), strFile->getSize());
2917282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        #if PRINT_STRING_METRICS
2918282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "**** type strings: %d\n", amt);
2919282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        #endif
2920282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        strAmt += amt;
2921282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (amt < 0) {
2922282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return amt;
2923282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2924282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t keyStringsStart = data->getSize();
2925282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        strFile = p->getKeyStringsData();
2926282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        amt = data->writeData(strFile->getData(), strFile->getSize());
2927282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        #if PRINT_STRING_METRICS
2928282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "**** key strings: %d\n", amt);
2929282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        #endif
2930282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        strAmt += amt;
2931282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (amt < 0) {
2932282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return amt;
2933282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2934282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
293527f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski        if (isBase) {
293627f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski            status_t err = flattenLibraryTable(data, libraryPackages);
293727f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski            if (err != NO_ERROR) {
293827f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski                fprintf(stderr, "ERROR: failed to write library table\n");
293927f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski                return err;
294027f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski            }
2941de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski        }
2942de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski
2943282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Build the type chunks inside of this package.
2944282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (size_t ti=0; ti<N; ti++) {
2945282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Retrieve them in the same order as the type string block.
2946282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            size_t len;
2947282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String16 typeName(p->getTypeStrings().stringAt(ti, &len));
2948282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<Type> t = p->getTypes().valueFor(typeName);
2949282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            LOG_ALWAYS_FATAL_IF(t == NULL && typeName != String16("<empty>"),
2950282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                "Type name %s not found",
2951282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                String8(typeName).string());
2952833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            if (t == NULL) {
2953833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                continue;
2954833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            }
2955282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const bool filterable = (typeName != mipmap16);
295627f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski            const bool skipEntireType = (typeName == mipmap16 && !isBase);
2957282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2958282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t N = t != NULL ? t->getOrderedConfigs().size() : 0;
2959282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2960282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Until a non-NO_ENTRY value has been written for a resource,
2961282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // that resource is invalid; validResources[i] represents
2962282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // the item at t->getOrderedConfigs().itemAt(i).
2963282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Vector<bool> validResources;
2964282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            validResources.insertAt(false, 0, N);
2965282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2966282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // First write the typeSpec chunk, containing information about
2967282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // each resource entry in this type.
2968282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            {
2969282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                const size_t typeSpecSize = sizeof(ResTable_typeSpec) + sizeof(uint32_t)*N;
2970282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                const size_t typeSpecStart = data->getSize();
2971282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ResTable_typeSpec* tsHeader = (ResTable_typeSpec*)
2972282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    (((uint8_t*)data->editData(typeSpecStart+typeSpecSize)) + typeSpecStart);
2973282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (tsHeader == NULL) {
2974282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    fprintf(stderr, "ERROR: out of memory creating ResTable_typeSpec\n");
2975282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return NO_MEMORY;
2976282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2977282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                memset(tsHeader, 0, sizeof(*tsHeader));
2978282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tsHeader->header.type = htods(RES_TABLE_TYPE_SPEC_TYPE);
2979282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tsHeader->header.headerSize = htods(sizeof(*tsHeader));
2980282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tsHeader->header.size = htodl(typeSpecSize);
2981282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tsHeader->id = ti+1;
2982282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tsHeader->entryCount = htodl(N);
2983282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2984282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                uint32_t* typeSpecFlags = (uint32_t*)
2985282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    (((uint8_t*)data->editData())
2986282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        + typeSpecStart + sizeof(ResTable_typeSpec));
2987282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                memset(typeSpecFlags, 0, sizeof(uint32_t)*N);
2988282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2989282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                for (size_t ei=0; ei<N; ei++) {
2990282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sp<ConfigList> cl = t->getOrderedConfigs().itemAt(ei);
29919b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski                    if (cl == NULL) {
29929b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski                        continue;
29939b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski                    }
29949b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski
2995282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (cl->getPublic()) {
2996282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        typeSpecFlags[ei] |= htodl(ResTable_typeSpec::SPEC_PUBLIC);
2997282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
299827f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski
299927f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski                    if (skipEntireType) {
300027f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski                        continue;
300127f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski                    }
300227f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski
3003282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    const size_t CN = cl->getEntries().size();
3004282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    for (size_t ci=0; ci<CN; ci++) {
3005fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                        if (filterable && !filter->match(cl->getEntries().keyAt(ci))) {
3006282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            continue;
3007282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
3008282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        for (size_t cj=ci+1; cj<CN; cj++) {
3009fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                            if (filterable && !filter->match(cl->getEntries().keyAt(cj))) {
3010282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                continue;
3011282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
3012282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            typeSpecFlags[ei] |= htodl(
3013282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                cl->getEntries().keyAt(ci).diff(cl->getEntries().keyAt(cj)));
3014282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
3015282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
3016282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3017282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3018282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
301927f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski            if (skipEntireType) {
302027f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski                continue;
302127f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski            }
302227f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski
3023282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // We need to write one type chunk for each configuration for
3024282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // which we have entries in this type.
30259b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski            const SortedVector<ConfigDescription> uniqueConfigs(t->getUniqueConfigs());
30269b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski            const size_t NC = uniqueConfigs.size();
3027282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3028282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t typeSize = sizeof(ResTable_type) + sizeof(uint32_t)*N;
3029282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3030282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t ci=0; ci<NC; ci++) {
30319b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski                const ConfigDescription& config = uniqueConfigs[ci];
3032282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3033282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                NOISY(printf("Writing config %d config: imsi:%d/%d lang:%c%c cnt:%c%c "
3034282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                     "orien:%d ui:%d touch:%d density:%d key:%d inp:%d nav:%d sz:%dx%d "
3035282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                     "sw%ddp w%ddp h%ddp dir:%d\n",
3036282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      ti+1,
3037282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.mcc, config.mnc,
3038282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.language[0] ? config.language[0] : '-',
3039282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.language[1] ? config.language[1] : '-',
3040282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.country[0] ? config.country[0] : '-',
3041282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.country[1] ? config.country[1] : '-',
3042282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.orientation,
3043282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.uiMode,
3044282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.touchscreen,
3045282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.density,
3046282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.keyboard,
3047282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.inputFlags,
3048282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.navigation,
3049282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.screenWidth,
3050282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.screenHeight,
3051282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.smallestScreenWidthDp,
3052282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.screenWidthDp,
3053282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.screenHeightDp,
3054282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.layoutDirection));
3055282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3056fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                if (filterable && !filter->match(config)) {
3057282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
3058282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3059282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3060282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                const size_t typeStart = data->getSize();
3061282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3062282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ResTable_type* tHeader = (ResTable_type*)
3063282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    (((uint8_t*)data->editData(typeStart+typeSize)) + typeStart);
3064282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (tHeader == NULL) {
3065282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    fprintf(stderr, "ERROR: out of memory creating ResTable_type\n");
3066282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return NO_MEMORY;
3067282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3068282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3069282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                memset(tHeader, 0, sizeof(*tHeader));
3070282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tHeader->header.type = htods(RES_TABLE_TYPE_TYPE);
3071282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tHeader->header.headerSize = htods(sizeof(*tHeader));
3072282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tHeader->id = ti+1;
3073282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tHeader->entryCount = htodl(N);
3074282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tHeader->entriesStart = htodl(typeSize);
3075282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tHeader->config = config;
3076282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                NOISY(printf("Writing type %d config: imsi:%d/%d lang:%c%c cnt:%c%c "
3077282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                     "orien:%d ui:%d touch:%d density:%d key:%d inp:%d nav:%d sz:%dx%d "
3078282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                     "sw%ddp w%ddp h%ddp dir:%d\n",
3079282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      ti+1,
3080282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.mcc, tHeader->config.mnc,
3081282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.language[0] ? tHeader->config.language[0] : '-',
3082282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.language[1] ? tHeader->config.language[1] : '-',
3083282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.country[0] ? tHeader->config.country[0] : '-',
3084282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.country[1] ? tHeader->config.country[1] : '-',
3085282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.orientation,
3086282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.uiMode,
3087282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.touchscreen,
3088282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.density,
3089282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.keyboard,
3090282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.inputFlags,
3091282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.navigation,
3092282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.screenWidth,
3093282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.screenHeight,
3094282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.smallestScreenWidthDp,
3095282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.screenWidthDp,
3096282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.screenHeightDp,
3097282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.layoutDirection));
3098282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tHeader->config.swapHtoD();
3099282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Build the entries inside of this type.
3101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                for (size_t ei=0; ei<N; ei++) {
3102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sp<ConfigList> cl = t->getOrderedConfigs().itemAt(ei);
31039b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski                    sp<Entry> e = NULL;
31049b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski                    if (cl != NULL) {
31059b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski                        e = cl->getEntries().valueFor(config);
31069b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski                    }
3107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // Set the offset for this entry in its type.
3109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    uint32_t* index = (uint32_t*)
3110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        (((uint8_t*)data->editData())
3111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            + typeStart + sizeof(ResTable_type));
3112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (e != NULL) {
3113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        index[ei] = htodl(data->getSize()-typeStart-typeSize);
3114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        // Create the entry.
3116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ssize_t amt = e->flatten(bundle, data, cl->getPublic());
3117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (amt < 0) {
3118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            return amt;
3119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
3120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        validResources.editItemAt(ei) = true;
3121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else {
3122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        index[ei] = htodl(ResTable_type::NO_ENTRY);
3123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
3124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Fill in the rest of the type information.
3127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tHeader = (ResTable_type*)
3128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    (((uint8_t*)data->editData()) + typeStart);
3129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tHeader->header.size = htodl(data->getSize()-typeStart);
3130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3132833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            // If we're building splits, then each invocation of the flattening
3133833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            // step will have 'missing' entries. Don't warn/error for this case.
3134833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            if (bundle->getSplitConfigurations().isEmpty()) {
3135833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                bool missing_entry = false;
3136833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                const char* log_prefix = bundle->getErrorOnMissingConfigEntry() ?
3137833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                        "error" : "warning";
3138833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                for (size_t i = 0; i < N; ++i) {
3139833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                    if (!validResources[i]) {
3140833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                        sp<ConfigList> c = t->getOrderedConfigs().itemAt(i);
31419b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski                        if (c != NULL) {
31429b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski                            fprintf(stderr, "%s: no entries written for %s/%s (0x%08x)\n", log_prefix,
31439b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski                                    String8(typeName).string(), String8(c->getName()).string(),
31449b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski                                    Res_MAKEID(p->getAssignedId() - 1, ti, i));
31459b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski                        }
3146833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                        missing_entry = true;
3147833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                    }
3148833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                }
3149833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                if (bundle->getErrorOnMissingConfigEntry() && missing_entry) {
3150833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                    fprintf(stderr, "Error: Missing entries, quit!\n");
3151833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                    return NOT_ENOUGH_DATA;
3152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3153cd28bd37ea2d88dd72930f032ca73daaad5744b4Ying Wang            }
3154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Fill in the rest of the package information.
3157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header = (ResTable_package*)data->editData();
3158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header->header.size = htodl(data->getSize());
3159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header->typeStrings = htodl(typeStringsStart);
3160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header->lastPublicType = htodl(p->getTypeStrings().size());
3161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header->keyStrings = htodl(keyStringsStart);
3162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header->lastPublicKey = htodl(p->getKeyStrings().size());
3163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        flatPackages.add(data);
3165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // And now write out the final chunks.
3168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t dataStart = dest->getSize();
3169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    {
3171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // blah
3172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ResTable_header header;
3173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        memset(&header, 0, sizeof(header));
3174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header.header.type = htods(RES_TABLE_TYPE);
3175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header.header.headerSize = htods(sizeof(header));
3176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header.packageCount = htodl(flatPackages.size());
3177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        status_t err = dest->writeData(&header, sizeof(header));
3178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != NO_ERROR) {
3179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: out of memory creating ResTable_header\n");
3180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return err;
3181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t strStart = dest->getSize();
3185fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    status_t err = valueStrings.writeStringBlock(dest);
3186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
3187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return err;
3188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t amt = (dest->getSize()-strStart);
3191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    strAmt += amt;
3192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    #if PRINT_STRING_METRICS
3193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(stderr, "**** value strings: %d\n", amt);
3194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(stderr, "**** total strings: %d\n", strAmt);
3195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    #endif
3196de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski
3197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (pi=0; pi<flatPackages.size(); pi++) {
3198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        err = dest->writeData(flatPackages[pi]->getData(),
3199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                              flatPackages[pi]->getSize());
3200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != NO_ERROR) {
3201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: out of memory creating package chunk for ResTable_header\n");
3202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return err;
3203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ResTable_header* header = (ResTable_header*)
3207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        (((uint8_t*)dest->getData()) + dataStart);
3208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    header->header.size = htodl(dest->getSize() - dataStart);
3209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    NOISY(aout << "Resource table:"
3211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski          << HexDump(dest->getData(), dest->getSize()) << endl);
3212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    #if PRINT_STRING_METRICS
3214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(stderr, "**** total resource table size: %d / %d%% strings\n",
3215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest->getSize(), (strAmt*100)/dest->getSize());
3216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    #endif
3217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
3219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3221de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinskistatus_t ResourceTable::flattenLibraryTable(const sp<AaptFile>& dest, const Vector<sp<Package> >& libs) {
3222de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski    // Write out the library table if necessary
3223de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski    if (libs.size() > 0) {
3224de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski        NOISY(fprintf(stderr, "Writing library reference table\n"));
3225de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski
3226de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski        const size_t libStart = dest->getSize();
3227de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski        const size_t count = libs.size();
32286022debdbcc4498736580640c6287b57872617a2Adam Lesinski        ResTable_lib_header* libHeader = (ResTable_lib_header*) dest->editDataInRange(
32296022debdbcc4498736580640c6287b57872617a2Adam Lesinski                libStart, sizeof(ResTable_lib_header));
3230de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski
3231de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski        memset(libHeader, 0, sizeof(*libHeader));
3232de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski        libHeader->header.type = htods(RES_TABLE_LIBRARY_TYPE);
3233de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski        libHeader->header.headerSize = htods(sizeof(*libHeader));
3234de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski        libHeader->header.size = htodl(sizeof(*libHeader) + (sizeof(ResTable_lib_entry) * count));
3235de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski        libHeader->count = htodl(count);
3236de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski
3237de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski        // Write the library entries
3238de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski        for (size_t i = 0; i < count; i++) {
3239de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski            const size_t entryStart = dest->getSize();
3240de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski            sp<Package> libPackage = libs[i];
3241de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski            NOISY(fprintf(stderr, "  Entry %s -> 0x%02x\n",
3242de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski                        String8(libPackage->getName()).string(),
3243de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski                        (uint8_t)libPackage->getAssignedId()));
3244de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski
32456022debdbcc4498736580640c6287b57872617a2Adam Lesinski            ResTable_lib_entry* entry = (ResTable_lib_entry*) dest->editDataInRange(
32466022debdbcc4498736580640c6287b57872617a2Adam Lesinski                    entryStart, sizeof(ResTable_lib_entry));
3247de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski            memset(entry, 0, sizeof(*entry));
3248de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski            entry->packageId = htodl(libPackage->getAssignedId());
3249de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski            strcpy16_htod(entry->packageName, libPackage->getName().string());
3250de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski        }
3251de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski    }
3252de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski    return NO_ERROR;
3253de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski}
3254de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski
3255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid ResourceTable::writePublicDefinitions(const String16& package, FILE* fp)
3256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(fp,
3258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    "<!-- This file contains <public> resource definitions for all\n"
3259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    "     resources that were generated from the source data. -->\n"
3260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    "\n"
3261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    "<resources>\n");
3262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    writePublicDefinitions(package, fp, true);
3264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    writePublicDefinitions(package, fp, false);
3265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(fp,
3267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    "\n"
3268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    "</resources>\n");
3269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid ResourceTable::writePublicDefinitions(const String16& package, FILE* fp, bool pub)
3272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool didHeader = false;
3274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Package> pkg = mPackages.valueFor(package);
3276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (pkg != NULL) {
3277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t NT = pkg->getOrderedTypes().size();
3278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (size_t i=0; i<NT; i++) {
3279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<Type> t = pkg->getOrderedTypes().itemAt(i);
3280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (t == NULL) {
3281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
3282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool didType = false;
3285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t NC = t->getOrderedConfigs().size();
3287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t j=0; j<NC; j++) {
3288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<ConfigList> c = t->getOrderedConfigs().itemAt(j);
3289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (c == NULL) {
3290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
3291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (c->getPublic() != pub) {
3294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
3295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!didType) {
3298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    fprintf(fp, "\n");
3299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    didType = true;
3300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!didHeader) {
3302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (pub) {
3303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        fprintf(fp,"  <!-- PUBLIC SECTION.  These resources have been declared public.\n");
3304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        fprintf(fp,"       Changes to these definitions will break binary compatibility. -->\n\n");
3305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else {
3306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        fprintf(fp,"  <!-- PRIVATE SECTION.  These resources have not been declared public.\n");
3307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        fprintf(fp,"       You can make them public my moving these lines into a file in res/values. -->\n\n");
3308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
3309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    didHeader = true;
3310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!pub) {
3312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    const size_t NE = c->getEntries().size();
3313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    for (size_t k=0; k<NE; k++) {
3314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const SourcePos& pos = c->getEntries().valueAt(k)->getPos();
3315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (pos.file != "") {
3316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            fprintf(fp,"  <!-- Declared at %s:%d -->\n",
3317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    pos.file.string(), pos.line);
3318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
3319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
3320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(fp, "  <public type=\"%s\" name=\"%s\" id=\"0x%08x\" />\n",
3322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8(t->getName()).string(),
3323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8(c->getName()).string(),
3324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        getResId(pkg, t, c->getEntryIndex()));
3325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3330282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiResourceTable::Item::Item(const SourcePos& _sourcePos,
3331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                          bool _isId,
3332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                          const String16& _value,
3333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                          const Vector<StringPool::entry_style_span>* _style,
3334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                          int32_t _format)
3335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    : sourcePos(_sourcePos)
3336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    , isId(_isId)
3337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    , value(_value)
3338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    , format(_format)
3339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    , bagKeyId(0)
3340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    , evaluating(false)
3341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (_style) {
3343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        style = *_style;
3344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
334782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam LesinskiResourceTable::Entry::Entry(const Entry& entry)
334882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    : RefBase()
334982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    , mName(entry.mName)
335082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    , mParent(entry.mParent)
335182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    , mType(entry.mType)
335282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    , mItem(entry.mItem)
335382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    , mItemFormat(entry.mItemFormat)
335482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    , mBag(entry.mBag)
335582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    , mNameIndex(entry.mNameIndex)
335682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    , mParentId(entry.mParentId)
335782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    , mPos(entry.mPos) {}
335882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski
3359978ab9d92934b79409638cf220de3002fea8d505Adam LesinskiResourceTable::Entry& ResourceTable::Entry::operator=(const Entry& entry) {
3360978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski    mName = entry.mName;
3361978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski    mParent = entry.mParent;
3362978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski    mType = entry.mType;
3363978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski    mItem = entry.mItem;
3364978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski    mItemFormat = entry.mItemFormat;
3365978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski    mBag = entry.mBag;
3366978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski    mNameIndex = entry.mNameIndex;
3367978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski    mParentId = entry.mParentId;
3368978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski    mPos = entry.mPos;
3369978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski    return *this;
3370978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski}
3371978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski
3372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Entry::makeItABag(const SourcePos& sourcePos)
3373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mType == TYPE_BAG) {
3375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NO_ERROR;
3376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mType == TYPE_UNKNOWN) {
3378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mType = TYPE_BAG;
3379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NO_ERROR;
3380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sourcePos.error("Resource entry %s is already defined as a single item.\n"
3382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    "%s:%d: Originally defined here.\n",
3383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(mName).string(),
3384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    mItem.sourcePos.file.string(), mItem.sourcePos.line);
3385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return UNKNOWN_ERROR;
3386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Entry::setItem(const SourcePos& sourcePos,
3389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       const String16& value,
3390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       const Vector<StringPool::entry_style_span>* style,
3391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       int32_t format,
3392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       const bool overwrite)
3393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Item item(sourcePos, false, value, style);
3395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mType == TYPE_BAG) {
339743a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski        if (mBag.size() == 0) {
339843a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski            sourcePos.error("Resource entry %s is already defined as a bag.",
339943a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski                    String8(mName).string());
340043a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski        } else {
340143a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski            const Item& item(mBag.valueAt(0));
340243a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski            sourcePos.error("Resource entry %s is already defined as a bag.\n"
340343a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski                            "%s:%d: Originally defined here.\n",
340443a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski                            String8(mName).string(),
340543a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski                            item.sourcePos.file.string(), item.sourcePos.line);
340643a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski        }
3407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
3408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if ( (mType != TYPE_UNKNOWN) && (overwrite == false) ) {
3410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sourcePos.error("Resource entry %s is already defined.\n"
3411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "%s:%d: Originally defined here.\n",
3412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8(mName).string(),
3413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        mItem.sourcePos.file.string(), mItem.sourcePos.line);
3414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
3415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mType = TYPE_ITEM;
3418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mItem = item;
3419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mItemFormat = format;
3420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
3421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Entry::addToBag(const SourcePos& sourcePos,
3424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        const String16& key, const String16& value,
3425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        const Vector<StringPool::entry_style_span>* style,
3426282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        bool replace, bool isId, int32_t format)
3427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = makeItABag(sourcePos);
3429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
3430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return err;
3431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Item item(sourcePos, isId, value, style, format);
3434282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // XXX NOTE: there is an error if you try to have a bag with two keys,
3436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // one an attr and one an id, with the same name.  Not something we
3437282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // currently ever have to worry about.
3438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t origKey = mBag.indexOfKey(key);
3439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (origKey >= 0) {
3440282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!replace) {
3441282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const Item& item(mBag.valueAt(origKey));
3442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sourcePos.error("Resource entry %s already has bag item %s.\n"
3443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    "%s:%d: Originally defined here.\n",
3444282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(mName).string(), String8(key).string(),
3445282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    item.sourcePos.file.string(), item.sourcePos.line);
3446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return UNKNOWN_ERROR;
3447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //printf("Replacing %s with %s\n",
3449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //       String8(mBag.valueFor(key).value).string(), String8(value).string());
3450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mBag.replaceValueFor(key, item);
3451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3452282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mBag.add(key, item);
3454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
3455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
345782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinskistatus_t ResourceTable::Entry::removeFromBag(const String16& key) {
345882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    if (mType != Entry::TYPE_BAG) {
345982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski        return NO_ERROR;
346082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    }
346182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski
346282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    if (mBag.removeItem(key) >= 0) {
346382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski        return NO_ERROR;
346482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    }
346582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    return UNKNOWN_ERROR;
346682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski}
346782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski
3468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Entry::emptyBag(const SourcePos& sourcePos)
3469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = makeItABag(sourcePos);
3471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
3472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return err;
3473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mBag.clear();
3476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
3477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3479282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Entry::generateAttributes(ResourceTable* table,
3480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                  const String16& package)
3481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 attr16("attr");
3483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 id16("id");
3484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t N = mBag.size();
3485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (size_t i=0; i<N; i++) {
3486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String16& key = mBag.keyAt(i);
3487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const Item& it = mBag.valueAt(i);
3488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (it.isId) {
3489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!table->hasBagOrEntry(key, &id16, &package)) {
3490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 value("false");
349143a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski                NOISY(fprintf(stderr, "Generating %s:id/%s\n",
349243a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski                        String8(package).string(),
349343a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski                        String8(key).string()));
3494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                status_t err = table->addEntry(SourcePos(String8("<generated>"), 0), package,
3495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                               id16, key, value);
3496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (err != NO_ERROR) {
3497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return err;
3498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else if (!table->hasBagOrEntry(key, &attr16, &package)) {
3501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#if 1
3503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//             fprintf(stderr, "ERROR: Bag attribute '%s' has not been defined.\n",
3504282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//                     String8(key).string());
3505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//             const Item& item(mBag.valueAt(i));
3506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//             fprintf(stderr, "Referenced from file %s line %d\n",
3507282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//                     item.sourcePos.file.string(), item.sourcePos.line);
3508282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//             return UNKNOWN_ERROR;
3509282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#else
3510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            char numberStr[16];
3511282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sprintf(numberStr, "%d", ResTable_map::TYPE_ANY);
3512282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            status_t err = table->addBag(SourcePos("<generated>", 0), package,
3513282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                         attr16, key, String16(""),
3514282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                         String16("^type"),
3515282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                         String16(numberStr), NULL, NULL);
3516282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (err != NO_ERROR) {
3517282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return err;
3518282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3519282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif
3520282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3521282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3522282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
3523282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3524282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3525282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Entry::assignResourceIds(ResourceTable* table,
3526282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                 const String16& package)
3527282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3528282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool hasErrors = false;
3529282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3530282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mType == TYPE_BAG) {
3531282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const char* errorMsg;
3532282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String16 style16("style");
3533282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String16 attr16("attr");
3534282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String16 id16("id");
3535282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mParentId = 0;
3536282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (mParent.size() > 0) {
3537282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mParentId = table->getResId(mParent, &style16, NULL, &errorMsg);
3538282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (mParentId == 0) {
3539282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                mPos.error("Error retrieving parent for item: %s '%s'.\n",
3540282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        errorMsg, String8(mParent).string());
3541282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                hasErrors = true;
3542282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3543282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3544282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t N = mBag.size();
3545282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (size_t i=0; i<N; i++) {
3546282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const String16& key = mBag.keyAt(i);
3547282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Item& it = mBag.editValueAt(i);
3548282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            it.bagKeyId = table->getResId(key,
3549282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    it.isId ? &id16 : &attr16, NULL, &errorMsg);
3550282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //printf("Bag key of %s: #%08x\n", String8(key).string(), it.bagKeyId);
3551282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (it.bagKeyId == 0) {
3552282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                it.sourcePos.error("Error: %s: %s '%s'.\n", errorMsg,
3553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8(it.isId ? id16 : attr16).string(),
3554282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8(key).string());
3555282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                hasErrors = true;
3556282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3557282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3558282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3559282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return hasErrors ? UNKNOWN_ERROR : NO_ERROR;
3560282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3561282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3562282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Entry::prepareFlatten(StringPool* strings, ResourceTable* table,
3563282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String8* configTypeName, const ConfigDescription* config)
3564282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3565282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mType == TYPE_ITEM) {
3566282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Item& it = mItem;
3567282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        AccessorCookie ac(it.sourcePos, String8(mName), String8(it.value));
3568282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!table->stringToValue(&it.parsedValue, strings,
3569282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  it.value, false, true, 0,
3570282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  &it.style, NULL, &ac, mItemFormat,
3571282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  configTypeName, config)) {
3572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return UNKNOWN_ERROR;
3573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else if (mType == TYPE_BAG) {
3575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t N = mBag.size();
3576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (size_t i=0; i<N; i++) {
3577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const String16& key = mBag.keyAt(i);
3578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Item& it = mBag.editValueAt(i);
3579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            AccessorCookie ac(it.sourcePos, String8(key), String8(it.value));
3580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!table->stringToValue(&it.parsedValue, strings,
3581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                      it.value, false, true, it.bagKeyId,
3582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                      &it.style, NULL, &ac, it.format,
3583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                      configTypeName, config)) {
3584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return UNKNOWN_ERROR;
3585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
3588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mPos.error("Error: entry %s is not a single item or a bag.\n",
3589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                   String8(mName).string());
3590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
3591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
3593282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Entry::remapStringValue(StringPool* strings)
3596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mType == TYPE_ITEM) {
3598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Item& it = mItem;
3599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (it.parsedValue.dataType == Res_value::TYPE_STRING) {
3600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            it.parsedValue.data = strings->mapOriginalPosToNewPos(it.parsedValue.data);
3601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else if (mType == TYPE_BAG) {
3603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t N = mBag.size();
3604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (size_t i=0; i<N; i++) {
3605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Item& it = mBag.editValueAt(i);
3606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (it.parsedValue.dataType == Res_value::TYPE_STRING) {
3607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                it.parsedValue.data = strings->mapOriginalPosToNewPos(it.parsedValue.data);
3608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
3611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mPos.error("Error: entry %s is not a single item or a bag.\n",
3612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                   String8(mName).string());
3613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
3614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
3616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskissize_t ResourceTable::Entry::flatten(Bundle* bundle, const sp<AaptFile>& data, bool isPublic)
3619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3620282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t amt = 0;
3621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ResTable_entry header;
3622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    memset(&header, 0, sizeof(header));
3623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    header.size = htods(sizeof(header));
3624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const type ty = this != NULL ? mType : TYPE_ITEM;
3625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (this != NULL) {
3626282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (ty == TYPE_BAG) {
3627282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            header.flags |= htods(header.FLAG_COMPLEX);
3628282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3629282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (isPublic) {
3630282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            header.flags |= htods(header.FLAG_PUBLIC);
3631282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3632282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header.key.index = htodl(mNameIndex);
3633282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3634282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (ty != TYPE_BAG) {
3635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        status_t err = data->writeData(&header, sizeof(header));
3636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != NO_ERROR) {
3637282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: out of memory creating ResTable_entry\n");
3638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return err;
3639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const Item& it = mItem;
3642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Res_value par;
3643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        memset(&par, 0, sizeof(par));
3644282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        par.size = htods(it.parsedValue.size);
3645282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        par.dataType = it.parsedValue.dataType;
3646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        par.res0 = it.parsedValue.res0;
3647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        par.data = htodl(it.parsedValue.data);
3648282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        #if 0
3649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printf("Writing item (%s): type=%d, data=0x%x, res0=0x%x\n",
3650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski               String8(mName).string(), it.parsedValue.dataType,
3651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski               it.parsedValue.data, par.res0);
3652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        #endif
3653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        err = data->writeData(&par, it.parsedValue.size);
3654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != NO_ERROR) {
3655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: out of memory creating Res_value\n");
3656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return err;
3657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        amt += it.parsedValue.size;
3659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
3660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        size_t N = mBag.size();
3661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        size_t i;
3662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Create correct ordering of items.
3663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        KeyedVector<uint32_t, const Item*> items;
3664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (i=0; i<N; i++) {
3665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const Item& it = mBag.valueAt(i);
3666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            items.add(it.bagKeyId, &it);
3667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        N = items.size();
3669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ResTable_map_entry mapHeader;
3671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        memcpy(&mapHeader, &header, sizeof(header));
3672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mapHeader.size = htods(sizeof(mapHeader));
3673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mapHeader.parent.ident = htodl(mParentId);
3674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mapHeader.count = htodl(N);
3675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        status_t err = data->writeData(&mapHeader, sizeof(mapHeader));
3676282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != NO_ERROR) {
3677282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: out of memory creating ResTable_entry\n");
3678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return err;
3679282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3680282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3681282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (i=0; i<N; i++) {
3682282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const Item& it = *items.valueAt(i);
3683282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ResTable_map map;
3684282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            map.name.ident = htodl(it.bagKeyId);
3685282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            map.value.size = htods(it.parsedValue.size);
3686282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            map.value.dataType = it.parsedValue.dataType;
3687282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            map.value.res0 = it.parsedValue.res0;
3688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            map.value.data = htodl(it.parsedValue.data);
3689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            err = data->writeData(&map, sizeof(map));
3690282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (err != NO_ERROR) {
3691282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, "ERROR: out of memory creating Res_value\n");
3692282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return err;
3693282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3694282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            amt += sizeof(map);
3695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3696282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return amt;
3698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3700282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid ResourceTable::ConfigList::appendComment(const String16& comment,
3701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                              bool onlyIfEmpty)
3702282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3703282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (comment.size() <= 0) {
3704282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return;
3705282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3706282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (onlyIfEmpty && mComment.size() > 0) {
3707282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return;
3708282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3709282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mComment.size() > 0) {
3710282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mComment.append(String16("\n"));
3711282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mComment.append(comment);
3713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3714282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid ResourceTable::ConfigList::appendTypeComment(const String16& comment)
3716282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3717282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (comment.size() <= 0) {
3718282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return;
3719282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3720282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mTypeComment.size() > 0) {
3721282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mTypeComment.append(String16("\n"));
3722282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3723282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mTypeComment.append(comment);
3724282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3725282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3726282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Type::addPublic(const SourcePos& sourcePos,
3727282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        const String16& name,
3728282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        const uint32_t ident)
3729282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3730282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    #if 0
3731282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int32_t entryIdx = Res_GETENTRY(ident);
3732282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (entryIdx < 0) {
3733282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sourcePos.error("Public resource %s/%s has an invalid 0 identifier (0x%08x).\n",
3734282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String8(mName).string(), String8(name).string(), ident);
3735282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
3736282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3737282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    #endif
3738282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3739282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int32_t typeIdx = Res_GETTYPE(ident);
3740282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (typeIdx >= 0) {
3741282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        typeIdx++;
3742282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (mPublicIndex > 0 && mPublicIndex != typeIdx) {
3743282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sourcePos.error("Public resource %s/%s has conflicting type codes for its"
3744282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    " public identifiers (0x%x vs 0x%x).\n",
3745282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(mName).string(), String8(name).string(),
3746282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    mPublicIndex, typeIdx);
3747282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return UNKNOWN_ERROR;
3748282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3749282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mPublicIndex = typeIdx;
3750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3751282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3752282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mFirstPublicSourcePos == NULL) {
3753282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mFirstPublicSourcePos = new SourcePos(sourcePos);
3754282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3755282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3756282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mPublic.indexOfKey(name) < 0) {
3757282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mPublic.add(name, Public(sourcePos, String16(), ident));
3758282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
3759282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Public& p = mPublic.editValueFor(name);
3760282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (p.ident != ident) {
3761282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sourcePos.error("Public resource %s/%s has conflicting public identifiers"
3762282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    " (0x%08x vs 0x%08x).\n"
3763282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    "%s:%d: Originally defined here.\n",
3764282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(mName).string(), String8(name).string(), p.ident, ident,
3765282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    p.sourcePos.file.string(), p.sourcePos.line);
3766282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return UNKNOWN_ERROR;
3767282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3768282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3769282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3770282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
3771282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid ResourceTable::Type::canAddEntry(const String16& name)
3774282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mCanAddEntries.add(name);
3776282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisp<ResourceTable::Entry> ResourceTable::Type::getEntry(const String16& entry,
3779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                       const SourcePos& sourcePos,
3780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                       const ResTable_config* config,
3781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                       bool doSetIndex,
3782282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                       bool overlay,
3783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                       bool autoAddOverlay)
3784282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int pos = -1;
3786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<ConfigList> c = mConfigs.valueFor(entry);
3787282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (c == NULL) {
3788282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (overlay && !autoAddOverlay && mCanAddEntries.indexOf(entry) < 0) {
3789282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sourcePos.error("Resource at %s appears in overlay but not"
3790282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            " in the base package; use <add-resource> to add.\n",
3791282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            String8(entry).string());
3792282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return NULL;
3793282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3794282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        c = new ConfigList(entry, sourcePos);
3795282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mConfigs.add(entry, c);
3796282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        pos = (int)mOrderedConfigs.size();
3797282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mOrderedConfigs.add(c);
3798282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (doSetIndex) {
3799282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            c->setEntryIndex(pos);
3800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3801282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3802282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3803282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ConfigDescription cdesc;
3804282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (config) cdesc = *config;
3805282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3806282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Entry> e = c->getEntries().valueFor(cdesc);
3807282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (e == NULL) {
3808282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (config != NULL) {
3809282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            NOISY(printf("New entry at %s:%d: imsi:%d/%d lang:%c%c cnt:%c%c "
3810282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    "orien:%d touch:%d density:%d key:%d inp:%d nav:%d sz:%dx%d "
3811282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    "sw%ddp w%ddp h%ddp dir:%d\n",
3812282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      sourcePos.file.string(), sourcePos.line,
3813282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->mcc, config->mnc,
3814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->language[0] ? config->language[0] : '-',
3815282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->language[1] ? config->language[1] : '-',
3816282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->country[0] ? config->country[0] : '-',
3817282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->country[1] ? config->country[1] : '-',
3818282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->orientation,
3819282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->touchscreen,
3820282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->density,
3821282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->keyboard,
3822282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->inputFlags,
3823282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->navigation,
3824282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->screenWidth,
3825282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->screenHeight,
3826282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->smallestScreenWidthDp,
3827282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->screenWidthDp,
3828282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->screenHeightDp,
3829282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->layoutDirection));
3830282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
3831282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            NOISY(printf("New entry at %s:%d: NULL config\n",
3832282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      sourcePos.file.string(), sourcePos.line));
3833282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3834282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        e = new Entry(entry, sourcePos);
3835282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        c->addEntry(cdesc, e);
3836282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        /*
3837282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (doSetIndex) {
3838282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (pos < 0) {
3839282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                for (pos=0; pos<(int)mOrderedConfigs.size(); pos++) {
3840282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (mOrderedConfigs[pos] == c) {
3841282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        break;
3842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
3843282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3844282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (pos >= (int)mOrderedConfigs.size()) {
3845282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sourcePos.error("Internal error: config not found in mOrderedConfigs when adding entry");
3846282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return NULL;
3847282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3848282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3849282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            e->setEntryIndex(pos);
3850282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3851282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        */
3852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3853282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3854282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return e;
3855282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3856282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
38579b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinskisp<ResourceTable::ConfigList> ResourceTable::Type::removeEntry(const String16& entry) {
38589b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski    ssize_t idx = mConfigs.indexOfKey(entry);
38599b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski    if (idx < 0) {
38609b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski        return NULL;
38619b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski    }
38629b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski
38639b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski    sp<ConfigList> removed = mConfigs.valueAt(idx);
38649b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski    mConfigs.removeItemsAt(idx);
38659b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski
38669b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski    Vector<sp<ConfigList> >::iterator iter = std::find(
38679b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski            mOrderedConfigs.begin(), mOrderedConfigs.end(), removed);
38689b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski    if (iter != mOrderedConfigs.end()) {
38699b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski        mOrderedConfigs.erase(iter);
38709b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski    }
38719b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski
38729b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski    mPublic.removeItem(entry);
38739b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski    return removed;
38749b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski}
38759b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski
38769b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam LesinskiSortedVector<ConfigDescription> ResourceTable::Type::getUniqueConfigs() const {
38779b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski    SortedVector<ConfigDescription> unique;
38789b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski    const size_t entryCount = mOrderedConfigs.size();
38799b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski    for (size_t i = 0; i < entryCount; i++) {
38809b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski        if (mOrderedConfigs[i] == NULL) {
38819b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski            continue;
38829b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski        }
38839b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski        const DefaultKeyedVector<ConfigDescription, sp<Entry> >& configs =
38849b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski                mOrderedConfigs[i]->getEntries();
38859b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski        const size_t configCount = configs.size();
38869b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski        for (size_t j = 0; j < configCount; j++) {
38879b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski            unique.add(configs.keyAt(j));
38889b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski        }
38899b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski    }
38909b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski    return unique;
38919b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski}
38929b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski
3893282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Type::applyPublicEntryOrder()
3894282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3895282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t N = mOrderedConfigs.size();
3896282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Vector<sp<ConfigList> > origOrder(mOrderedConfigs);
3897282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool hasError = false;
3898282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3899282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t i;
3900282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (i=0; i<N; i++) {
3901282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mOrderedConfigs.replaceAt(NULL, i);
3902282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3903282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3904282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t NP = mPublic.size();
3905282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //printf("Ordering %d configs from %d public defs\n", N, NP);
3906282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t j;
3907282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (j=0; j<NP; j++) {
3908282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String16& name = mPublic.keyAt(j);
3909282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const Public& p = mPublic.valueAt(j);
3910282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int32_t idx = Res_GETENTRY(p.ident);
3911282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //printf("Looking for entry \"%s\"/\"%s\" (0x%08x) in %d...\n",
3912282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //       String8(mName).string(), String8(name).string(), p.ident, N);
3913282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        bool found = false;
3914282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (i=0; i<N; i++) {
3915282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<ConfigList> e = origOrder.itemAt(i);
3916282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //printf("#%d: \"%s\"\n", i, String8(e->getName()).string());
3917282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (e->getName() == name) {
3918282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (idx >= (int32_t)mOrderedConfigs.size()) {
39199b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski                    mOrderedConfigs.resize(idx + 1);
39209b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski                }
39219b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski
39229b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski                if (mOrderedConfigs.itemAt(idx) == NULL) {
3923282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    e->setPublic(true);
3924282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    e->setPublicSourcePos(p.sourcePos);
3925282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    mOrderedConfigs.replaceAt(e, idx);
3926282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    origOrder.removeAt(i);
3927282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    N--;
3928282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    found = true;
3929282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    break;
3930282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
3931282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sp<ConfigList> oe = mOrderedConfigs.itemAt(idx);
3932282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3933282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    p.sourcePos.error("Multiple entry names declared for public entry"
3934282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            " identifier 0x%x in type %s (%s vs %s).\n"
3935282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            "%s:%d: Originally defined here.",
3936282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            idx+1, String8(mName).string(),
3937282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            String8(oe->getName()).string(),
3938282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            String8(name).string(),
3939282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            oe->getPublicSourcePos().file.string(),
3940282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            oe->getPublicSourcePos().line);
3941282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasError = true;
3942282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3943282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3944282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3945282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3946282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!found) {
3947282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            p.sourcePos.error("Public symbol %s/%s declared here is not defined.",
3948282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(mName).string(), String8(name).string());
3949282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            hasError = true;
3950282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3951282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3952282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3953282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //printf("Copying back in %d non-public configs, have %d\n", N, origOrder.size());
3954282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3955282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (N != origOrder.size()) {
3956282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printf("Internal error: remaining private symbol count mismatch\n");
3957282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        N = origOrder.size();
3958282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3959282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3960282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    j = 0;
3961282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (i=0; i<N; i++) {
3962282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<ConfigList> e = origOrder.itemAt(i);
3963282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // There will always be enough room for the remaining entries.
3964282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        while (mOrderedConfigs.itemAt(j) != NULL) {
3965282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            j++;
3966282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3967282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mOrderedConfigs.replaceAt(e, j);
3968282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        j++;
3969282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3970282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3971282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return hasError ? UNKNOWN_ERROR : NO_ERROR;
3972282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3973282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3974833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam LesinskiResourceTable::Package::Package(const String16& name, size_t packageId)
3975833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    : mName(name), mPackageId(packageId),
3976282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      mTypeStringsMapping(0xffffffff),
3977282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      mKeyStringsMapping(0xffffffff)
3978282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3979282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3980282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3981282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisp<ResourceTable::Type> ResourceTable::Package::getType(const String16& type,
3982282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                        const SourcePos& sourcePos,
3983282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                        bool doSetIndex)
3984282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3985282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Type> t = mTypes.valueFor(type);
3986282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (t == NULL) {
3987282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        t = new Type(type, sourcePos);
3988282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mTypes.add(type, t);
3989282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mOrderedTypes.add(t);
3990282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (doSetIndex) {
3991282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // For some reason the type's index is set to one plus the index
3992282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // in the mOrderedTypes list, rather than just the index.
3993282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            t->setIndex(mOrderedTypes.size());
3994282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3995282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3996282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return t;
3997282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3998282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3999282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Package::setTypeStrings(const sp<AaptFile>& data)
4000282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
4001282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = setStrings(data, &mTypeStrings, &mTypeStringsMapping);
4002282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
4003282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: Type string data is corrupt!\n");
400457079519f4610715e4c0668c641575d10f3d4461Adam Lesinski        return err;
4005282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
400657079519f4610715e4c0668c641575d10f3d4461Adam Lesinski
400757079519f4610715e4c0668c641575d10f3d4461Adam Lesinski    // Retain a reference to the new data after we've successfully replaced
400857079519f4610715e4c0668c641575d10f3d4461Adam Lesinski    // all uses of the old reference (in setStrings() ).
400957079519f4610715e4c0668c641575d10f3d4461Adam Lesinski    mTypeStringsData = data;
401057079519f4610715e4c0668c641575d10f3d4461Adam Lesinski    return NO_ERROR;
4011282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
4012282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4013282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Package::setKeyStrings(const sp<AaptFile>& data)
4014282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
4015282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = setStrings(data, &mKeyStrings, &mKeyStringsMapping);
4016282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
4017282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: Key string data is corrupt!\n");
401857079519f4610715e4c0668c641575d10f3d4461Adam Lesinski        return err;
4019282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
402057079519f4610715e4c0668c641575d10f3d4461Adam Lesinski
402157079519f4610715e4c0668c641575d10f3d4461Adam Lesinski    // Retain a reference to the new data after we've successfully replaced
402257079519f4610715e4c0668c641575d10f3d4461Adam Lesinski    // all uses of the old reference (in setStrings() ).
402357079519f4610715e4c0668c641575d10f3d4461Adam Lesinski    mKeyStringsData = data;
402457079519f4610715e4c0668c641575d10f3d4461Adam Lesinski    return NO_ERROR;
4025282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
4026282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4027282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Package::setStrings(const sp<AaptFile>& data,
4028282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                            ResStringPool* strings,
4029282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                            DefaultKeyedVector<String16, uint32_t>* mappings)
4030282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
4031282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (data->getData() == NULL) {
4032282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
4033282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
4034282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4035282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    NOISY(aout << "Setting restable string pool: "
4036282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski          << HexDump(data->getData(), data->getSize()) << endl);
4037282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4038282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = strings->setTo(data->getData(), data->getSize());
4039282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err == NO_ERROR) {
4040282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t N = strings->size();
4041282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (size_t i=0; i<N; i++) {
4042282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            size_t len;
4043282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mappings->add(String16(strings->stringAt(i, &len)), i);
4044282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
4045282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
4046282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return err;
4047282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
4048282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4049282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Package::applyPublicTypeOrder()
4050282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
4051282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t N = mOrderedTypes.size();
4052282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Vector<sp<Type> > origOrder(mOrderedTypes);
4053282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4054282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t i;
4055282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (i=0; i<N; i++) {
4056282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mOrderedTypes.replaceAt(NULL, i);
4057282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
4058282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4059282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (i=0; i<N; i++) {
4060282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Type> t = origOrder.itemAt(i);
4061282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int32_t idx = t->getPublicIndex();
4062282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (idx > 0) {
4063282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            idx--;
4064282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            while (idx >= (int32_t)mOrderedTypes.size()) {
4065282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                mOrderedTypes.add();
4066282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
4067282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (mOrderedTypes.itemAt(idx) != NULL) {
4068282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<Type> ot = mOrderedTypes.itemAt(idx);
4069282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                t->getFirstPublicSourcePos().error("Multiple type names declared for public type"
4070282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        " identifier 0x%x (%s vs %s).\n"
4071282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "%s:%d: Originally defined here.",
4072282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        idx, String8(ot->getName()).string(),
4073282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8(t->getName()).string(),
4074282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ot->getFirstPublicSourcePos().file.string(),
4075282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ot->getFirstPublicSourcePos().line);
4076282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return UNKNOWN_ERROR;
4077282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
4078282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mOrderedTypes.replaceAt(t, idx);
4079282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            origOrder.removeAt(i);
4080282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            i--;
4081282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            N--;
4082282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
4083282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
4084282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4085282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t j=0;
4086282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (i=0; i<N; i++) {
4087282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Type> t = origOrder.itemAt(i);
4088282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // There will always be enough room for the remaining types.
4089282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        while (mOrderedTypes.itemAt(j) != NULL) {
4090282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            j++;
4091282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
4092282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mOrderedTypes.replaceAt(t, j);
4093282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
4094282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4095282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
4096282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
4097282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
40989b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinskivoid ResourceTable::Package::movePrivateAttrs() {
40999b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski    sp<Type> attr = mTypes.valueFor(String16("attr"));
41009b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski    if (attr == NULL) {
41019b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski        // Nothing to do.
41029b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski        return;
41039b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski    }
41049b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski
41059b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski    Vector<sp<ConfigList> > privateAttrs;
41069b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski
41079b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski    bool hasPublic = false;
41089b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski    const Vector<sp<ConfigList> >& configs = attr->getOrderedConfigs();
41099b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski    const size_t configCount = configs.size();
41109b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski    for (size_t i = 0; i < configCount; i++) {
41119b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski        if (configs[i] == NULL) {
41129b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski            continue;
41139b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski        }
41149b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski
41159b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski        if (attr->isPublic(configs[i]->getName())) {
41169b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski            hasPublic = true;
41179b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski        } else {
41189b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski            privateAttrs.add(configs[i]);
41199b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski        }
41209b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski    }
41219b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski
41229b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski    // Only if we have public attributes do we create a separate type for
41239b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski    // private attributes.
41249b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski    if (!hasPublic) {
41259b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski        return;
41269b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski    }
41279b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski
41289b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski    // Create a new type for private attributes.
41299b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski    sp<Type> privateAttrType = getType(String16(kAttrPrivateType), SourcePos());
41309b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski
41319b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski    const size_t privateAttrCount = privateAttrs.size();
41329b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski    for (size_t i = 0; i < privateAttrCount; i++) {
41339b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski        const sp<ConfigList>& cl = privateAttrs[i];
41349b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski
41359b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski        // Remove the private attributes from their current type.
41369b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski        attr->removeEntry(cl->getName());
41379b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski
41389b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski        // Add it to the new type.
41399b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski        const DefaultKeyedVector<ConfigDescription, sp<Entry> >& entries = cl->getEntries();
41409b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski        const size_t entryCount = entries.size();
41419b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski        for (size_t j = 0; j < entryCount; j++) {
41429b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski            const sp<Entry>& oldEntry = entries[j];
41439b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski            sp<Entry> entry = privateAttrType->getEntry(
41449b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski                    cl->getName(), oldEntry->getPos(), &entries.keyAt(j));
41459b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski            *entry = *oldEntry;
41469b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski        }
41479b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski
41489b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski        // Move the symbols to the new type.
41499b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski
41509b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski    }
41519b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski}
41529b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski
4153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisp<ResourceTable::Package> ResourceTable::getPackage(const String16& package)
4154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
4155833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    if (package != mAssetsPackage) {
4156833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        return NULL;
4157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
4158833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    return mPackages.valueFor(package);
4159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
4160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisp<ResourceTable::Type> ResourceTable::getType(const String16& package,
4162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                               const String16& type,
4163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                               const SourcePos& sourcePos,
4164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                               bool doSetIndex)
4165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
4166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Package> p = getPackage(package);
4167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (p == NULL) {
4168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NULL;
4169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
4170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return p->getType(type, sourcePos, doSetIndex);
4171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
4172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisp<ResourceTable::Entry> ResourceTable::getEntry(const String16& package,
4174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                 const String16& type,
4175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                 const String16& name,
4176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                 const SourcePos& sourcePos,
4177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                 bool overlay,
4178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                 const ResTable_config* config,
4179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                 bool doSetIndex)
4180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
4181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Type> t = getType(package, type, sourcePos, doSetIndex);
4182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (t == NULL) {
4183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NULL;
4184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
4185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return t->getEntry(name, sourcePos, config, doSetIndex, overlay, mBundle->getAutoAddOverlay());
4186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
4187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4188e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinskisp<ResourceTable::ConfigList> ResourceTable::getConfigList(const String16& package,
4189e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        const String16& type, const String16& name) const
4190e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski{
4191e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    const size_t packageCount = mOrderedPackages.size();
4192e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    for (size_t pi = 0; pi < packageCount; pi++) {
4193e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        const sp<Package>& p = mOrderedPackages[pi];
4194e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        if (p == NULL || p->getName() != package) {
4195e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski            continue;
4196e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        }
4197e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski
4198e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        const Vector<sp<Type> >& types = p->getOrderedTypes();
4199e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        const size_t typeCount = types.size();
4200e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        for (size_t ti = 0; ti < typeCount; ti++) {
4201e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski            const sp<Type>& t = types[ti];
4202e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski            if (t == NULL || t->getName() != type) {
4203e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                continue;
4204e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski            }
4205e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski
4206e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski            const Vector<sp<ConfigList> >& configs = t->getOrderedConfigs();
4207e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski            const size_t configCount = configs.size();
4208e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski            for (size_t ci = 0; ci < configCount; ci++) {
4209e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                const sp<ConfigList>& cl = configs[ci];
4210e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                if (cl == NULL || cl->getName() != name) {
4211e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                    continue;
4212e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                }
4213e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski
4214e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                return cl;
4215e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski            }
4216e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        }
4217e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    }
4218e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    return NULL;
4219e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski}
4220e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski
4221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisp<const ResourceTable::Entry> ResourceTable::getEntry(uint32_t resID,
4222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                       const ResTable_config* config) const
4223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
4224833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    size_t pid = Res_GETPACKAGE(resID)+1;
4225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t N = mOrderedPackages.size();
4226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Package> p;
4227833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    for (size_t i = 0; i < N; i++) {
4228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Package> check = mOrderedPackages[i];
4229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (check->getAssignedId() == pid) {
4230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            p = check;
4231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            break;
4232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
4233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
4235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (p == NULL) {
4236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "warning: Package not found for resource #%08x\n", resID);
4237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NULL;
4238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
4239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int tid = Res_GETTYPE(resID);
4241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (tid < 0 || tid >= (int)p->getOrderedTypes().size()) {
4242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "warning: Type not found for resource #%08x\n", resID);
4243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NULL;
4244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
4245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Type> t = p->getOrderedTypes()[tid];
4246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int eid = Res_GETENTRY(resID);
4248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (eid < 0 || eid >= (int)t->getOrderedConfigs().size()) {
4249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "warning: Entry not found for resource #%08x\n", resID);
4250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NULL;
4251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
4252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<ConfigList> c = t->getOrderedConfigs()[eid];
4254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (c == NULL) {
4255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "warning: Entry not found for resource #%08x\n", resID);
4256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NULL;
4257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
4258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ConfigDescription cdesc;
4260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (config) cdesc = *config;
4261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Entry> e = c->getEntries().valueFor(cdesc);
4262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (c == NULL) {
4263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "warning: Entry configuration not found for resource #%08x\n", resID);
4264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NULL;
4265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
4266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return e;
4268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
4269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiconst ResourceTable::Item* ResourceTable::getItem(uint32_t resID, uint32_t attrID) const
4271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
4272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<const Entry> e = getEntry(resID);
4273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (e == NULL) {
4274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NULL;
4275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
4276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t N = e->getBag().size();
4278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (size_t i=0; i<N; i++) {
4279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const Item& it = e->getBag().valueAt(i);
4280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (it.bagKeyId == 0) {
4281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "warning: ID not yet assigned to '%s' in bag '%s'\n",
4282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(e->getName()).string(),
4283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(e->getBag().keyAt(i)).string());
4284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
4285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (it.bagKeyId == attrID) {
4286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return &it;
4287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
4288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
4289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NULL;
4291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
4292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::getItemValue(
4294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t resID, uint32_t attrID, Res_value* outValue)
4295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
4296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const Item* item = getItem(resID, attrID);
4297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool res = false;
4299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (item != NULL) {
4300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (item->evaluating) {
4301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<const Entry> e = getEntry(resID);
4302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t N = e->getBag().size();
4303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            size_t i;
4304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (i=0; i<N; i++) {
4305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (&e->getBag().valueAt(i) == item) {
4306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    break;
4307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
4308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
4309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "warning: Circular reference detected in key '%s' of bag '%s'\n",
4310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(e->getName()).string(),
4311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(e->getBag().keyAt(i)).string());
4312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;
4313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
4314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        item->evaluating = true;
4315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        res = stringToValue(outValue, NULL, item->value, false, false, item->bagKeyId);
4316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        NOISY(
4317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (res) {
4318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("getItemValue of #%08x[#%08x] (%s): type=#%08x, data=#%08x\n",
4319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       resID, attrID, String8(getEntry(resID)->getName()).string(),
4320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       outValue->dataType, outValue->data);
4321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
4322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("getItemValue of #%08x[#%08x]: failed\n",
4323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       resID, attrID);
4324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
4325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        );
4326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        item->evaluating = false;
4327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
4328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return res;
4329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
433082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski
433182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski/**
433228994d8d181c286b39811441ce78399576c2d315Adam Lesinski * Returns the SDK version at which the attribute was
433328994d8d181c286b39811441ce78399576c2d315Adam Lesinski * made public, or -1 if the resource ID is not an attribute
433428994d8d181c286b39811441ce78399576c2d315Adam Lesinski * or is not public.
433582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski */
433628994d8d181c286b39811441ce78399576c2d315Adam Lesinskiint ResourceTable::getPublicAttributeSdkLevel(uint32_t attrId) const {
433728994d8d181c286b39811441ce78399576c2d315Adam Lesinski    if (Res_GETPACKAGE(attrId) + 1 != 0x01 || Res_GETTYPE(attrId) + 1 != 0x01) {
433828994d8d181c286b39811441ce78399576c2d315Adam Lesinski        return -1;
433982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    }
434082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski
434182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    uint32_t specFlags;
434282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    if (!mAssets->getIncludedResources().getResourceFlags(attrId, &specFlags)) {
434328994d8d181c286b39811441ce78399576c2d315Adam Lesinski        return -1;
434428994d8d181c286b39811441ce78399576c2d315Adam Lesinski    }
434528994d8d181c286b39811441ce78399576c2d315Adam Lesinski
434628994d8d181c286b39811441ce78399576c2d315Adam Lesinski    if ((specFlags & ResTable_typeSpec::SPEC_PUBLIC) == 0) {
434728994d8d181c286b39811441ce78399576c2d315Adam Lesinski        return -1;
434828994d8d181c286b39811441ce78399576c2d315Adam Lesinski    }
434928994d8d181c286b39811441ce78399576c2d315Adam Lesinski
435028994d8d181c286b39811441ce78399576c2d315Adam Lesinski    const size_t entryId = Res_GETENTRY(attrId);
435128994d8d181c286b39811441ce78399576c2d315Adam Lesinski    if (entryId <= 0x021c) {
435228994d8d181c286b39811441ce78399576c2d315Adam Lesinski        return 1;
435328994d8d181c286b39811441ce78399576c2d315Adam Lesinski    } else if (entryId <= 0x021d) {
435428994d8d181c286b39811441ce78399576c2d315Adam Lesinski        return 2;
435528994d8d181c286b39811441ce78399576c2d315Adam Lesinski    } else if (entryId <= 0x0269) {
435628994d8d181c286b39811441ce78399576c2d315Adam Lesinski        return SDK_CUPCAKE;
435728994d8d181c286b39811441ce78399576c2d315Adam Lesinski    } else if (entryId <= 0x028d) {
435828994d8d181c286b39811441ce78399576c2d315Adam Lesinski        return SDK_DONUT;
435928994d8d181c286b39811441ce78399576c2d315Adam Lesinski    } else if (entryId <= 0x02ad) {
436028994d8d181c286b39811441ce78399576c2d315Adam Lesinski        return SDK_ECLAIR;
436128994d8d181c286b39811441ce78399576c2d315Adam Lesinski    } else if (entryId <= 0x02b3) {
436228994d8d181c286b39811441ce78399576c2d315Adam Lesinski        return SDK_ECLAIR_0_1;
436328994d8d181c286b39811441ce78399576c2d315Adam Lesinski    } else if (entryId <= 0x02b5) {
436428994d8d181c286b39811441ce78399576c2d315Adam Lesinski        return SDK_ECLAIR_MR1;
436528994d8d181c286b39811441ce78399576c2d315Adam Lesinski    } else if (entryId <= 0x02bd) {
436628994d8d181c286b39811441ce78399576c2d315Adam Lesinski        return SDK_FROYO;
436728994d8d181c286b39811441ce78399576c2d315Adam Lesinski    } else if (entryId <= 0x02cb) {
436828994d8d181c286b39811441ce78399576c2d315Adam Lesinski        return SDK_GINGERBREAD;
436928994d8d181c286b39811441ce78399576c2d315Adam Lesinski    } else if (entryId <= 0x0361) {
437028994d8d181c286b39811441ce78399576c2d315Adam Lesinski        return SDK_HONEYCOMB;
437128994d8d181c286b39811441ce78399576c2d315Adam Lesinski    } else if (entryId <= 0x0366) {
437228994d8d181c286b39811441ce78399576c2d315Adam Lesinski        return SDK_HONEYCOMB_MR1;
437328994d8d181c286b39811441ce78399576c2d315Adam Lesinski    } else if (entryId <= 0x03a6) {
437428994d8d181c286b39811441ce78399576c2d315Adam Lesinski        return SDK_HONEYCOMB_MR2;
437528994d8d181c286b39811441ce78399576c2d315Adam Lesinski    } else if (entryId <= 0x03ae) {
437628994d8d181c286b39811441ce78399576c2d315Adam Lesinski        return SDK_JELLY_BEAN;
437728994d8d181c286b39811441ce78399576c2d315Adam Lesinski    } else if (entryId <= 0x03cc) {
437828994d8d181c286b39811441ce78399576c2d315Adam Lesinski        return SDK_JELLY_BEAN_MR1;
437928994d8d181c286b39811441ce78399576c2d315Adam Lesinski    } else if (entryId <= 0x03da) {
438028994d8d181c286b39811441ce78399576c2d315Adam Lesinski        return SDK_JELLY_BEAN_MR2;
438128994d8d181c286b39811441ce78399576c2d315Adam Lesinski    } else if (entryId <= 0x03f1) {
438228994d8d181c286b39811441ce78399576c2d315Adam Lesinski        return SDK_KITKAT;
438328994d8d181c286b39811441ce78399576c2d315Adam Lesinski    } else if (entryId <= 0x03f6) {
438428994d8d181c286b39811441ce78399576c2d315Adam Lesinski        return SDK_KITKAT_WATCH;
438528994d8d181c286b39811441ce78399576c2d315Adam Lesinski    } else if (entryId <= 0x04ce) {
438628994d8d181c286b39811441ce78399576c2d315Adam Lesinski        return SDK_LOLLIPOP;
438728994d8d181c286b39811441ce78399576c2d315Adam Lesinski    } else {
438828994d8d181c286b39811441ce78399576c2d315Adam Lesinski        // Anything else is marked as defined in
438928994d8d181c286b39811441ce78399576c2d315Adam Lesinski        // SDK_LOLLIPOP_MR1 since after this
439028994d8d181c286b39811441ce78399576c2d315Adam Lesinski        // version no attribute compat work
439128994d8d181c286b39811441ce78399576c2d315Adam Lesinski        // needs to be done.
439228994d8d181c286b39811441ce78399576c2d315Adam Lesinski        return SDK_LOLLIPOP_MR1;
439382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    }
439482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski}
439582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski
439628994d8d181c286b39811441ce78399576c2d315Adam Lesinski/**
439728994d8d181c286b39811441ce78399576c2d315Adam Lesinski * First check the Manifest, then check the command line flag.
439828994d8d181c286b39811441ce78399576c2d315Adam Lesinski */
439928994d8d181c286b39811441ce78399576c2d315Adam Lesinskistatic int getMinSdkVersion(const Bundle* bundle) {
440028994d8d181c286b39811441ce78399576c2d315Adam Lesinski    if (bundle->getManifestMinSdkVersion() != NULL && strlen(bundle->getManifestMinSdkVersion()) > 0) {
440128994d8d181c286b39811441ce78399576c2d315Adam Lesinski        return atoi(bundle->getManifestMinSdkVersion());
440228994d8d181c286b39811441ce78399576c2d315Adam Lesinski    } else if (bundle->getMinSdkVersion() != NULL && strlen(bundle->getMinSdkVersion()) > 0) {
440328994d8d181c286b39811441ce78399576c2d315Adam Lesinski        return atoi(bundle->getMinSdkVersion());
4404e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    }
440528994d8d181c286b39811441ce78399576c2d315Adam Lesinski    return 0;
4406e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski}
4407e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski
440882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski/**
440982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * Modifies the entries in the resource table to account for compatibility
441082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * issues with older versions of Android.
441182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski *
441282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * This primarily handles the issue of private/public attribute clashes
441382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * in framework resources.
441482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski *
441582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * AAPT has traditionally assigned resource IDs to public attributes,
441682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * and then followed those public definitions with private attributes.
441782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski *
441882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * --- PUBLIC ---
441982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * | 0x01010234 | attr/color
442082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * | 0x01010235 | attr/background
442182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski *
442282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * --- PRIVATE ---
442382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * | 0x01010236 | attr/secret
442482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * | 0x01010237 | attr/shhh
442582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski *
442682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * Each release, when attributes are added, they take the place of the private
442782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * attributes and the private attributes are shifted down again.
442882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski *
442982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * --- PUBLIC ---
443082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * | 0x01010234 | attr/color
443182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * | 0x01010235 | attr/background
443282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * | 0x01010236 | attr/shinyNewAttr
443382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * | 0x01010237 | attr/highlyValuedFeature
443482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski *
443582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * --- PRIVATE ---
443682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * | 0x01010238 | attr/secret
443782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * | 0x01010239 | attr/shhh
443882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski *
443982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * Platform code may look for private attributes set in a theme. If an app
444082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * compiled against a newer version of the platform uses a new public
444182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * attribute that happens to have the same ID as the private attribute
444282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * the older platform is expecting, then the behavior is undefined.
444382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski *
444482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * We get around this by detecting any newly defined attributes (in L),
444582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * copy the resource into a -v21 qualified resource, and delete the
444682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * attribute from the original resource. This ensures that older platforms
444782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * don't see the new attribute, but when running on L+ platforms, the
444882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * attribute will be respected.
444982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski */
445082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinskistatus_t ResourceTable::modifyForCompat(const Bundle* bundle) {
445128994d8d181c286b39811441ce78399576c2d315Adam Lesinski    const int minSdk = getMinSdkVersion(bundle);
445228994d8d181c286b39811441ce78399576c2d315Adam Lesinski    if (minSdk >= SDK_LOLLIPOP_MR1) {
445328994d8d181c286b39811441ce78399576c2d315Adam Lesinski        // Lollipop MR1 and up handles public attributes differently, no
445428994d8d181c286b39811441ce78399576c2d315Adam Lesinski        // need to do any compat modifications.
4455e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        return NO_ERROR;
445682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    }
445782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski
445882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    const String16 attr16("attr");
445982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski
446082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    const size_t packageCount = mOrderedPackages.size();
446182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    for (size_t pi = 0; pi < packageCount; pi++) {
446282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski        sp<Package> p = mOrderedPackages.itemAt(pi);
446382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski        if (p == NULL || p->getTypes().size() == 0) {
446482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski            // Empty, skip!
446582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski            continue;
446682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski        }
446782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski
446882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski        const size_t typeCount = p->getOrderedTypes().size();
446982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski        for (size_t ti = 0; ti < typeCount; ti++) {
447082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski            sp<Type> t = p->getOrderedTypes().itemAt(ti);
447182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski            if (t == NULL) {
447282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                continue;
447382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski            }
447482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski
447582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski            const size_t configCount = t->getOrderedConfigs().size();
447682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski            for (size_t ci = 0; ci < configCount; ci++) {
447782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                sp<ConfigList> c = t->getOrderedConfigs().itemAt(ci);
447882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                if (c == NULL) {
447982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                    continue;
448082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                }
448182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski
448282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                Vector<key_value_pair_t<ConfigDescription, sp<Entry> > > entriesToAdd;
448382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                const DefaultKeyedVector<ConfigDescription, sp<Entry> >& entries =
448482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                        c->getEntries();
448582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                const size_t entryCount = entries.size();
448682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                for (size_t ei = 0; ei < entryCount; ei++) {
448782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                    sp<Entry> e = entries.valueAt(ei);
448882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                    if (e == NULL || e->getType() != Entry::TYPE_BAG) {
448982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                        continue;
449082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                    }
449182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski
449282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                    const ConfigDescription& config = entries.keyAt(ei);
449328994d8d181c286b39811441ce78399576c2d315Adam Lesinski                    if (config.sdkVersion >= SDK_LOLLIPOP_MR1) {
449482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                        continue;
449582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                    }
449682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski
449728994d8d181c286b39811441ce78399576c2d315Adam Lesinski                    KeyedVector<int, Vector<String16> > attributesToRemove;
449882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                    const KeyedVector<String16, Item>& bag = e->getBag();
449982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                    const size_t bagCount = bag.size();
450082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                    for (size_t bi = 0; bi < bagCount; bi++) {
450182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                        const Item& item = bag.valueAt(bi);
450282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                        const uint32_t attrId = getResId(bag.keyAt(bi), &attr16);
450328994d8d181c286b39811441ce78399576c2d315Adam Lesinski                        const int sdkLevel = getPublicAttributeSdkLevel(attrId);
450428994d8d181c286b39811441ce78399576c2d315Adam Lesinski                        if (sdkLevel > 1 && sdkLevel > config.sdkVersion && sdkLevel > minSdk) {
450528994d8d181c286b39811441ce78399576c2d315Adam Lesinski                            AaptUtil::appendValue(attributesToRemove, sdkLevel, bag.keyAt(bi));
450682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                        }
450782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                    }
450882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski
450982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                    if (attributesToRemove.isEmpty()) {
451082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                        continue;
451182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                    }
451282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski
451328994d8d181c286b39811441ce78399576c2d315Adam Lesinski                    const size_t sdkCount = attributesToRemove.size();
451428994d8d181c286b39811441ce78399576c2d315Adam Lesinski                    for (size_t i = 0; i < sdkCount; i++) {
451528994d8d181c286b39811441ce78399576c2d315Adam Lesinski                        const int sdkLevel = attributesToRemove.keyAt(i);
451628994d8d181c286b39811441ce78399576c2d315Adam Lesinski
451728994d8d181c286b39811441ce78399576c2d315Adam Lesinski                        // Duplicate the entry under the same configuration
451828994d8d181c286b39811441ce78399576c2d315Adam Lesinski                        // but with sdkVersion == sdkLevel.
451928994d8d181c286b39811441ce78399576c2d315Adam Lesinski                        ConfigDescription newConfig(config);
452028994d8d181c286b39811441ce78399576c2d315Adam Lesinski                        newConfig.sdkVersion = sdkLevel;
452128994d8d181c286b39811441ce78399576c2d315Adam Lesinski
452228994d8d181c286b39811441ce78399576c2d315Adam Lesinski                        sp<Entry> newEntry = new Entry(*e);
452328994d8d181c286b39811441ce78399576c2d315Adam Lesinski
452428994d8d181c286b39811441ce78399576c2d315Adam Lesinski                        // Remove all items that have a higher SDK level than
452528994d8d181c286b39811441ce78399576c2d315Adam Lesinski                        // the one we are synthesizing.
452628994d8d181c286b39811441ce78399576c2d315Adam Lesinski                        for (size_t j = 0; j < sdkCount; j++) {
452728994d8d181c286b39811441ce78399576c2d315Adam Lesinski                            if (j == i) {
452828994d8d181c286b39811441ce78399576c2d315Adam Lesinski                                continue;
452928994d8d181c286b39811441ce78399576c2d315Adam Lesinski                            }
453028994d8d181c286b39811441ce78399576c2d315Adam Lesinski
453128994d8d181c286b39811441ce78399576c2d315Adam Lesinski                            if (attributesToRemove.keyAt(j) > sdkLevel) {
453228994d8d181c286b39811441ce78399576c2d315Adam Lesinski                                const size_t attrCount = attributesToRemove[j].size();
453328994d8d181c286b39811441ce78399576c2d315Adam Lesinski                                for (size_t k = 0; k < attrCount; k++) {
453428994d8d181c286b39811441ce78399576c2d315Adam Lesinski                                    newEntry->removeFromBag(attributesToRemove[j][k]);
453528994d8d181c286b39811441ce78399576c2d315Adam Lesinski                                }
453628994d8d181c286b39811441ce78399576c2d315Adam Lesinski                            }
453728994d8d181c286b39811441ce78399576c2d315Adam Lesinski                        }
453828994d8d181c286b39811441ce78399576c2d315Adam Lesinski
453928994d8d181c286b39811441ce78399576c2d315Adam Lesinski                        entriesToAdd.add(key_value_pair_t<ConfigDescription, sp<Entry> >(
454028994d8d181c286b39811441ce78399576c2d315Adam Lesinski                                newConfig, newEntry));
454128994d8d181c286b39811441ce78399576c2d315Adam Lesinski                    }
454282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski
454382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                    // Remove the attribute from the original.
454482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                    for (size_t i = 0; i < attributesToRemove.size(); i++) {
454528994d8d181c286b39811441ce78399576c2d315Adam Lesinski                        for (size_t j = 0; j < attributesToRemove[i].size(); j++) {
454628994d8d181c286b39811441ce78399576c2d315Adam Lesinski                            e->removeFromBag(attributesToRemove[i][j]);
454728994d8d181c286b39811441ce78399576c2d315Adam Lesinski                        }
454882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                    }
454982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                }
455082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski
455182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                const size_t entriesToAddCount = entriesToAdd.size();
455282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                for (size_t i = 0; i < entriesToAddCount; i++) {
455382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                    if (entries.indexOfKey(entriesToAdd[i].key) >= 0) {
455482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                        // An entry already exists for this config.
455582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                        // That means that any attributes that were
455682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                        // defined in L in the original bag will be overriden
455782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                        // anyways on L devices, so we do nothing.
455882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                        continue;
455982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                    }
456082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski
4561f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski                    if (bundle->getVerbose()) {
4562f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski                        entriesToAdd[i].value->getPos()
4563f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski                                .printf("using v%d attributes; synthesizing resource %s:%s/%s for configuration %s.",
456428994d8d181c286b39811441ce78399576c2d315Adam Lesinski                                        entriesToAdd[i].key.sdkVersion,
4565f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski                                        String8(p->getName()).string(),
4566f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski                                        String8(t->getName()).string(),
4567f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski                                        String8(entriesToAdd[i].value->getName()).string(),
4568f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski                                        entriesToAdd[i].key.toString().string());
4569f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski                    }
457082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski
4571978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski                    sp<Entry> newEntry = t->getEntry(c->getName(),
4572978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski                            entriesToAdd[i].value->getPos(),
4573978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski                            &entriesToAdd[i].key);
4574978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski
4575978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski                    *newEntry = *entriesToAdd[i].value;
457682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski                }
457782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski            }
457882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski        }
457982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    }
458082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski    return NO_ERROR;
458182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski}
4582e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski
4583e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinskistatus_t ResourceTable::modifyForCompat(const Bundle* bundle,
4584e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                                        const String16& resourceName,
4585e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                                        const sp<AaptFile>& target,
4586e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                                        const sp<XMLNode>& root) {
458728994d8d181c286b39811441ce78399576c2d315Adam Lesinski    const int minSdk = getMinSdkVersion(bundle);
458828994d8d181c286b39811441ce78399576c2d315Adam Lesinski    if (minSdk >= SDK_LOLLIPOP_MR1) {
458928994d8d181c286b39811441ce78399576c2d315Adam Lesinski        // Lollipop MR1 and up handles public attributes differently, no
459028994d8d181c286b39811441ce78399576c2d315Adam Lesinski        // need to do any compat modifications.
4591e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        return NO_ERROR;
4592e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    }
4593e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski
459428994d8d181c286b39811441ce78399576c2d315Adam Lesinski    const ConfigDescription config(target->getGroupEntry().toParams());
459528994d8d181c286b39811441ce78399576c2d315Adam Lesinski    if (target->getResourceType() == "" || config.sdkVersion >= SDK_LOLLIPOP_MR1) {
4596e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        // Skip resources that have no type (AndroidManifest.xml) or are already version qualified with v21
4597e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        // or higher.
4598e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        return NO_ERROR;
4599e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    }
4600e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski
4601ea4e5ecc27793b5c1dd2eda291f752b3f900ee6cAdam Lesinski    sp<XMLNode> newRoot = NULL;
460228994d8d181c286b39811441ce78399576c2d315Adam Lesinski    ConfigDescription newConfig(target->getGroupEntry().toParams());
460328994d8d181c286b39811441ce78399576c2d315Adam Lesinski    newConfig.sdkVersion = SDK_LOLLIPOP_MR1;
4604e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski
4605e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    Vector<sp<XMLNode> > nodesToVisit;
4606e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    nodesToVisit.push(root);
4607e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    while (!nodesToVisit.isEmpty()) {
4608e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        sp<XMLNode> node = nodesToVisit.top();
4609e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        nodesToVisit.pop();
4610e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski
4611e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        const Vector<XMLNode::attribute_entry>& attrs = node->getAttributes();
4612ea4e5ecc27793b5c1dd2eda291f752b3f900ee6cAdam Lesinski        for (size_t i = 0; i < attrs.size(); i++) {
4613e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski            const XMLNode::attribute_entry& attr = attrs[i];
461428994d8d181c286b39811441ce78399576c2d315Adam Lesinski            const int sdkLevel = getPublicAttributeSdkLevel(attr.nameResId);
461528994d8d181c286b39811441ce78399576c2d315Adam Lesinski            if (sdkLevel > 1 && sdkLevel > config.sdkVersion && sdkLevel > minSdk) {
4616ea4e5ecc27793b5c1dd2eda291f752b3f900ee6cAdam Lesinski                if (newRoot == NULL) {
4617ea4e5ecc27793b5c1dd2eda291f752b3f900ee6cAdam Lesinski                    newRoot = root->clone();
4618ea4e5ecc27793b5c1dd2eda291f752b3f900ee6cAdam Lesinski                }
4619ea4e5ecc27793b5c1dd2eda291f752b3f900ee6cAdam Lesinski
462028994d8d181c286b39811441ce78399576c2d315Adam Lesinski                // Find the smallest sdk version that we need to synthesize for
462128994d8d181c286b39811441ce78399576c2d315Adam Lesinski                // and do that one. Subsequent versions will be processed on
462228994d8d181c286b39811441ce78399576c2d315Adam Lesinski                // the next pass.
462328994d8d181c286b39811441ce78399576c2d315Adam Lesinski                if (sdkLevel < newConfig.sdkVersion) {
462428994d8d181c286b39811441ce78399576c2d315Adam Lesinski                    newConfig.sdkVersion = sdkLevel;
462528994d8d181c286b39811441ce78399576c2d315Adam Lesinski                }
462628994d8d181c286b39811441ce78399576c2d315Adam Lesinski
4627ea4e5ecc27793b5c1dd2eda291f752b3f900ee6cAdam Lesinski                if (bundle->getVerbose()) {
4628ea4e5ecc27793b5c1dd2eda291f752b3f900ee6cAdam Lesinski                    SourcePos(node->getFilename(), node->getStartLineNumber()).printf(
4629ea4e5ecc27793b5c1dd2eda291f752b3f900ee6cAdam Lesinski                            "removing attribute %s%s%s from <%s>",
4630ea4e5ecc27793b5c1dd2eda291f752b3f900ee6cAdam Lesinski                            String8(attr.ns).string(),
4631ea4e5ecc27793b5c1dd2eda291f752b3f900ee6cAdam Lesinski                            (attr.ns.size() == 0 ? "" : ":"),
4632ea4e5ecc27793b5c1dd2eda291f752b3f900ee6cAdam Lesinski                            String8(attr.name).string(),
4633ea4e5ecc27793b5c1dd2eda291f752b3f900ee6cAdam Lesinski                            String8(node->getElementName()).string());
4634ea4e5ecc27793b5c1dd2eda291f752b3f900ee6cAdam Lesinski                }
4635ea4e5ecc27793b5c1dd2eda291f752b3f900ee6cAdam Lesinski                node->removeAttribute(i);
4636ea4e5ecc27793b5c1dd2eda291f752b3f900ee6cAdam Lesinski                i--;
4637e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski            }
4638e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        }
4639e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski
4640e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        // Schedule a visit to the children.
4641e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        const Vector<sp<XMLNode> >& children = node->getChildren();
4642e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        const size_t childCount = children.size();
4643e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        for (size_t i = 0; i < childCount; i++) {
4644e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski            nodesToVisit.push(children[i]);
4645e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        }
4646e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    }
4647e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski
4648ea4e5ecc27793b5c1dd2eda291f752b3f900ee6cAdam Lesinski    if (newRoot == NULL) {
4649e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        return NO_ERROR;
4650e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    }
4651e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski
4652e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    // Look to see if we already have an overriding v21 configuration.
4653e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    sp<ConfigList> cl = getConfigList(String16(mAssets->getPackage()),
4654e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski            String16(target->getResourceType()), resourceName);
4655e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    if (cl->getEntries().indexOfKey(newConfig) < 0) {
4656e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        // We don't have an overriding entry for v21, so we must duplicate this one.
4657e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        sp<AaptFile> newFile = new AaptFile(target->getSourceFile(),
4658e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                AaptGroupEntry(newConfig), target->getResourceType());
4659e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        String8 resPath = String8::format("res/%s/%s",
4660e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                newFile->getGroupEntry().toDirName(target->getResourceType()).string(),
4661aff7c2447df1ddfe094628317b6d22121cd657f8Adam Lesinski                target->getSourceFile().getPathLeaf().string());
4662e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        resPath.convertToResPath();
4663e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski
4664e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        // Add a resource table entry.
4665f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski        if (bundle->getVerbose()) {
4666f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski            SourcePos(target->getSourceFile(), -1).printf(
4667f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski                    "using v%d attributes; synthesizing resource %s:%s/%s for configuration %s.",
466828994d8d181c286b39811441ce78399576c2d315Adam Lesinski                    newConfig.sdkVersion,
4669f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski                    mAssets->getPackage().string(),
4670f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski                    newFile->getResourceType().string(),
4671f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski                    String8(resourceName).string(),
4672f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski                    newConfig.toString().string());
4673f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski        }
4674e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski
4675e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        addEntry(SourcePos(),
4676e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                String16(mAssets->getPackage()),
4677e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                String16(target->getResourceType()),
4678e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                resourceName,
4679e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                String16(resPath),
4680e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                NULL,
4681e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski                &newConfig);
4682e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski
4683e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        // Schedule this to be compiled.
4684e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        CompileResourceWorkItem item;
4685e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        item.resourceName = resourceName;
4686e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        item.resPath = resPath;
4687e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        item.file = newFile;
4688e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski        mWorkQueue.push(item);
4689e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    }
4690e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski
4691e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski    return NO_ERROR;
4692e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski}
4693de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski
4694de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinskivoid ResourceTable::getDensityVaryingResources(KeyedVector<Symbol, Vector<SymbolDefinition> >& resources) {
4695de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski    const ConfigDescription nullConfig;
4696de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski
4697de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski    const size_t packageCount = mOrderedPackages.size();
4698de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski    for (size_t p = 0; p < packageCount; p++) {
4699de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski        const Vector<sp<Type> >& types = mOrderedPackages[p]->getOrderedTypes();
4700de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski        const size_t typeCount = types.size();
4701de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski        for (size_t t = 0; t < typeCount; t++) {
4702de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski            const Vector<sp<ConfigList> >& configs = types[t]->getOrderedConfigs();
4703de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski            const size_t configCount = configs.size();
4704de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski            for (size_t c = 0; c < configCount; c++) {
4705de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski                const DefaultKeyedVector<ConfigDescription, sp<Entry> >& configEntries = configs[c]->getEntries();
4706de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski                const size_t configEntryCount = configEntries.size();
4707de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski                for (size_t ce = 0; ce < configEntryCount; ce++) {
4708de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski                    const ConfigDescription& config = configEntries.keyAt(ce);
4709de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski                    if (AaptConfig::isDensityOnly(config)) {
4710de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski                        // This configuration only varies with regards to density.
4711de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski                        const Symbol symbol(mOrderedPackages[p]->getName(),
4712de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski                                types[t]->getName(),
4713de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski                                configs[c]->getName(),
4714de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski                                getResId(mOrderedPackages[p], types[t], configs[c]->getEntryIndex()));
4715de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski
4716de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski                        const sp<Entry>& entry = configEntries.valueAt(ce);
4717de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski                        AaptUtil::appendValue(resources, symbol, SymbolDefinition(symbol, config, entry->getPos()));
4718de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski                    }
4719de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski                }
4720de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski            }
4721de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski        }
4722de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski    }
4723de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski}
4724