1*d57664e9SAndroid Build Coastguard Worker //
2*d57664e9SAndroid Build Coastguard Worker // Copyright 2006 The Android Open Source Project
3*d57664e9SAndroid Build Coastguard Worker //
4*d57664e9SAndroid Build Coastguard Worker
5*d57664e9SAndroid Build Coastguard Worker #include "AaptAssets.h"
6*d57664e9SAndroid Build Coastguard Worker #include "AaptConfig.h"
7*d57664e9SAndroid Build Coastguard Worker #include "AaptUtil.h"
8*d57664e9SAndroid Build Coastguard Worker #include "Main.h"
9*d57664e9SAndroid Build Coastguard Worker #include "ResourceFilter.h"
10*d57664e9SAndroid Build Coastguard Worker #include "Utils.h"
11*d57664e9SAndroid Build Coastguard Worker
12*d57664e9SAndroid Build Coastguard Worker #include <androidfw/PathUtils.h>
13*d57664e9SAndroid Build Coastguard Worker #include <utils/misc.h>
14*d57664e9SAndroid Build Coastguard Worker #include <utils/SortedVector.h>
15*d57664e9SAndroid Build Coastguard Worker
16*d57664e9SAndroid Build Coastguard Worker #include <ctype.h>
17*d57664e9SAndroid Build Coastguard Worker #include <dirent.h>
18*d57664e9SAndroid Build Coastguard Worker #include <errno.h>
19*d57664e9SAndroid Build Coastguard Worker
20*d57664e9SAndroid Build Coastguard Worker static const char* kAssetDir = "assets";
21*d57664e9SAndroid Build Coastguard Worker static const char* kResourceDir = "res";
22*d57664e9SAndroid Build Coastguard Worker static const char* kValuesDir = "values";
23*d57664e9SAndroid Build Coastguard Worker static const char* kMipmapDir = "mipmap";
24*d57664e9SAndroid Build Coastguard Worker static const char* kInvalidChars = "/\\:";
25*d57664e9SAndroid Build Coastguard Worker static const size_t kMaxAssetFileName = 100;
26*d57664e9SAndroid Build Coastguard Worker
27*d57664e9SAndroid Build Coastguard Worker static const String8 kResString(kResourceDir);
28*d57664e9SAndroid Build Coastguard Worker
29*d57664e9SAndroid Build Coastguard Worker /*
30*d57664e9SAndroid Build Coastguard Worker * Names of asset files must meet the following criteria:
31*d57664e9SAndroid Build Coastguard Worker *
32*d57664e9SAndroid Build Coastguard Worker * - the filename length must be less than kMaxAssetFileName bytes long
33*d57664e9SAndroid Build Coastguard Worker * (and can't be empty)
34*d57664e9SAndroid Build Coastguard Worker * - all characters must be 7-bit printable ASCII
35*d57664e9SAndroid Build Coastguard Worker * - none of { '/' '\\' ':' }
36*d57664e9SAndroid Build Coastguard Worker *
37*d57664e9SAndroid Build Coastguard Worker * Pass in just the filename, not the full path.
38*d57664e9SAndroid Build Coastguard Worker */
validateFileName(const char * fileName)39*d57664e9SAndroid Build Coastguard Worker static bool validateFileName(const char* fileName)
40*d57664e9SAndroid Build Coastguard Worker {
41*d57664e9SAndroid Build Coastguard Worker const char* cp = fileName;
42*d57664e9SAndroid Build Coastguard Worker size_t len = 0;
43*d57664e9SAndroid Build Coastguard Worker
44*d57664e9SAndroid Build Coastguard Worker while (*cp != '\0') {
45*d57664e9SAndroid Build Coastguard Worker if ((*cp & 0x80) != 0)
46*d57664e9SAndroid Build Coastguard Worker return false; // reject high ASCII
47*d57664e9SAndroid Build Coastguard Worker if (*cp < 0x20 || *cp >= 0x7f)
48*d57664e9SAndroid Build Coastguard Worker return false; // reject control chars and 0x7f
49*d57664e9SAndroid Build Coastguard Worker if (strchr(kInvalidChars, *cp) != NULL)
50*d57664e9SAndroid Build Coastguard Worker return false; // reject path sep chars
51*d57664e9SAndroid Build Coastguard Worker cp++;
52*d57664e9SAndroid Build Coastguard Worker len++;
53*d57664e9SAndroid Build Coastguard Worker }
54*d57664e9SAndroid Build Coastguard Worker
55*d57664e9SAndroid Build Coastguard Worker if (len < 1 || len > kMaxAssetFileName)
56*d57664e9SAndroid Build Coastguard Worker return false; // reject empty or too long
57*d57664e9SAndroid Build Coastguard Worker
58*d57664e9SAndroid Build Coastguard Worker return true;
59*d57664e9SAndroid Build Coastguard Worker }
60*d57664e9SAndroid Build Coastguard Worker
61*d57664e9SAndroid Build Coastguard Worker // The default to use if no other ignore pattern is defined.
62*d57664e9SAndroid Build Coastguard Worker const char * const gDefaultIgnoreAssets =
63*d57664e9SAndroid Build Coastguard Worker "!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~";
64*d57664e9SAndroid Build Coastguard Worker // The ignore pattern that can be passed via --ignore-assets in Main.cpp
65*d57664e9SAndroid Build Coastguard Worker const char * gUserIgnoreAssets = NULL;
66*d57664e9SAndroid Build Coastguard Worker
isHidden(const char * root,const char * path)67*d57664e9SAndroid Build Coastguard Worker static bool isHidden(const char *root, const char *path)
68*d57664e9SAndroid Build Coastguard Worker {
69*d57664e9SAndroid Build Coastguard Worker // Patterns syntax:
70*d57664e9SAndroid Build Coastguard Worker // - Delimiter is :
71*d57664e9SAndroid Build Coastguard Worker // - Entry can start with the flag ! to avoid printing a warning
72*d57664e9SAndroid Build Coastguard Worker // about the file being ignored.
73*d57664e9SAndroid Build Coastguard Worker // - Entry can have the flag "<dir>" to match only directories
74*d57664e9SAndroid Build Coastguard Worker // or <file> to match only files. Default is to match both.
75*d57664e9SAndroid Build Coastguard Worker // - Entry can be a simplified glob "<prefix>*" or "*<suffix>"
76*d57664e9SAndroid Build Coastguard Worker // where prefix/suffix must have at least 1 character (so that
77*d57664e9SAndroid Build Coastguard Worker // we don't match a '*' catch-all pattern.)
78*d57664e9SAndroid Build Coastguard Worker // - The special filenames "." and ".." are always ignored.
79*d57664e9SAndroid Build Coastguard Worker // - Otherwise the full string is matched.
80*d57664e9SAndroid Build Coastguard Worker // - match is not case-sensitive.
81*d57664e9SAndroid Build Coastguard Worker
82*d57664e9SAndroid Build Coastguard Worker if (strcmp(path, ".") == 0 || strcmp(path, "..") == 0) {
83*d57664e9SAndroid Build Coastguard Worker return true;
84*d57664e9SAndroid Build Coastguard Worker }
85*d57664e9SAndroid Build Coastguard Worker
86*d57664e9SAndroid Build Coastguard Worker const char *delim = ":";
87*d57664e9SAndroid Build Coastguard Worker const char *p = gUserIgnoreAssets;
88*d57664e9SAndroid Build Coastguard Worker if (!p || !p[0]) {
89*d57664e9SAndroid Build Coastguard Worker p = getenv("ANDROID_AAPT_IGNORE");
90*d57664e9SAndroid Build Coastguard Worker }
91*d57664e9SAndroid Build Coastguard Worker if (!p || !p[0]) {
92*d57664e9SAndroid Build Coastguard Worker p = gDefaultIgnoreAssets;
93*d57664e9SAndroid Build Coastguard Worker }
94*d57664e9SAndroid Build Coastguard Worker char *patterns = strdup(p);
95*d57664e9SAndroid Build Coastguard Worker
96*d57664e9SAndroid Build Coastguard Worker bool ignore = false;
97*d57664e9SAndroid Build Coastguard Worker bool chatty = true;
98*d57664e9SAndroid Build Coastguard Worker char *matchedPattern = NULL;
99*d57664e9SAndroid Build Coastguard Worker
100*d57664e9SAndroid Build Coastguard Worker String8 fullPath(root);
101*d57664e9SAndroid Build Coastguard Worker appendPath(fullPath, String8(path));
102*d57664e9SAndroid Build Coastguard Worker FileType type = getFileType(fullPath.c_str());
103*d57664e9SAndroid Build Coastguard Worker
104*d57664e9SAndroid Build Coastguard Worker int plen = strlen(path);
105*d57664e9SAndroid Build Coastguard Worker
106*d57664e9SAndroid Build Coastguard Worker // Note: we don't have strtok_r under mingw.
107*d57664e9SAndroid Build Coastguard Worker for(char *token = strtok(patterns, delim);
108*d57664e9SAndroid Build Coastguard Worker !ignore && token != NULL;
109*d57664e9SAndroid Build Coastguard Worker token = strtok(NULL, delim)) {
110*d57664e9SAndroid Build Coastguard Worker chatty = token[0] != '!';
111*d57664e9SAndroid Build Coastguard Worker if (!chatty) token++; // skip !
112*d57664e9SAndroid Build Coastguard Worker if (strncasecmp(token, "<dir>" , 5) == 0) {
113*d57664e9SAndroid Build Coastguard Worker if (type != kFileTypeDirectory) continue;
114*d57664e9SAndroid Build Coastguard Worker token += 5;
115*d57664e9SAndroid Build Coastguard Worker }
116*d57664e9SAndroid Build Coastguard Worker if (strncasecmp(token, "<file>", 6) == 0) {
117*d57664e9SAndroid Build Coastguard Worker if (type != kFileTypeRegular) continue;
118*d57664e9SAndroid Build Coastguard Worker token += 6;
119*d57664e9SAndroid Build Coastguard Worker }
120*d57664e9SAndroid Build Coastguard Worker
121*d57664e9SAndroid Build Coastguard Worker matchedPattern = token;
122*d57664e9SAndroid Build Coastguard Worker int n = strlen(token);
123*d57664e9SAndroid Build Coastguard Worker
124*d57664e9SAndroid Build Coastguard Worker if (token[0] == '*') {
125*d57664e9SAndroid Build Coastguard Worker // Match *suffix
126*d57664e9SAndroid Build Coastguard Worker token++;
127*d57664e9SAndroid Build Coastguard Worker n--;
128*d57664e9SAndroid Build Coastguard Worker if (n <= plen) {
129*d57664e9SAndroid Build Coastguard Worker ignore = strncasecmp(token, path + plen - n, n) == 0;
130*d57664e9SAndroid Build Coastguard Worker }
131*d57664e9SAndroid Build Coastguard Worker } else if (n > 1 && token[n - 1] == '*') {
132*d57664e9SAndroid Build Coastguard Worker // Match prefix*
133*d57664e9SAndroid Build Coastguard Worker ignore = strncasecmp(token, path, n - 1) == 0;
134*d57664e9SAndroid Build Coastguard Worker } else {
135*d57664e9SAndroid Build Coastguard Worker ignore = strcasecmp(token, path) == 0;
136*d57664e9SAndroid Build Coastguard Worker }
137*d57664e9SAndroid Build Coastguard Worker }
138*d57664e9SAndroid Build Coastguard Worker
139*d57664e9SAndroid Build Coastguard Worker if (ignore && chatty) {
140*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, " (skipping %s '%s' due to ANDROID_AAPT_IGNORE pattern '%s')\n",
141*d57664e9SAndroid Build Coastguard Worker type == kFileTypeDirectory ? "dir" : "file",
142*d57664e9SAndroid Build Coastguard Worker path,
143*d57664e9SAndroid Build Coastguard Worker matchedPattern ? matchedPattern : "");
144*d57664e9SAndroid Build Coastguard Worker }
145*d57664e9SAndroid Build Coastguard Worker
146*d57664e9SAndroid Build Coastguard Worker free(patterns);
147*d57664e9SAndroid Build Coastguard Worker return ignore;
148*d57664e9SAndroid Build Coastguard Worker }
149*d57664e9SAndroid Build Coastguard Worker
150*d57664e9SAndroid Build Coastguard Worker // =========================================================================
151*d57664e9SAndroid Build Coastguard Worker // =========================================================================
152*d57664e9SAndroid Build Coastguard Worker // =========================================================================
153*d57664e9SAndroid Build Coastguard Worker
154*d57664e9SAndroid Build Coastguard Worker /* static */
isAlpha(const String8 & string)155*d57664e9SAndroid Build Coastguard Worker inline bool isAlpha(const String8& string) {
156*d57664e9SAndroid Build Coastguard Worker const size_t length = string.length();
157*d57664e9SAndroid Build Coastguard Worker for (size_t i = 0; i < length; ++i) {
158*d57664e9SAndroid Build Coastguard Worker if (!isalpha(string[i])) {
159*d57664e9SAndroid Build Coastguard Worker return false;
160*d57664e9SAndroid Build Coastguard Worker }
161*d57664e9SAndroid Build Coastguard Worker }
162*d57664e9SAndroid Build Coastguard Worker
163*d57664e9SAndroid Build Coastguard Worker return true;
164*d57664e9SAndroid Build Coastguard Worker }
165*d57664e9SAndroid Build Coastguard Worker
166*d57664e9SAndroid Build Coastguard Worker /* static */
isNumber(const String8 & string)167*d57664e9SAndroid Build Coastguard Worker inline bool isNumber(const String8& string) {
168*d57664e9SAndroid Build Coastguard Worker const size_t length = string.length();
169*d57664e9SAndroid Build Coastguard Worker for (size_t i = 0; i < length; ++i) {
170*d57664e9SAndroid Build Coastguard Worker if (!isdigit(string[i])) {
171*d57664e9SAndroid Build Coastguard Worker return false;
172*d57664e9SAndroid Build Coastguard Worker }
173*d57664e9SAndroid Build Coastguard Worker }
174*d57664e9SAndroid Build Coastguard Worker
175*d57664e9SAndroid Build Coastguard Worker return true;
176*d57664e9SAndroid Build Coastguard Worker }
177*d57664e9SAndroid Build Coastguard Worker
setLanguage(const char * languageChars)178*d57664e9SAndroid Build Coastguard Worker void AaptLocaleValue::setLanguage(const char* languageChars) {
179*d57664e9SAndroid Build Coastguard Worker size_t i = 0;
180*d57664e9SAndroid Build Coastguard Worker while ((*languageChars) != '\0' && i < sizeof(language)/sizeof(language[0])) {
181*d57664e9SAndroid Build Coastguard Worker language[i++] = tolower(*languageChars);
182*d57664e9SAndroid Build Coastguard Worker languageChars++;
183*d57664e9SAndroid Build Coastguard Worker }
184*d57664e9SAndroid Build Coastguard Worker }
185*d57664e9SAndroid Build Coastguard Worker
setRegion(const char * regionChars)186*d57664e9SAndroid Build Coastguard Worker void AaptLocaleValue::setRegion(const char* regionChars) {
187*d57664e9SAndroid Build Coastguard Worker size_t i = 0;
188*d57664e9SAndroid Build Coastguard Worker while ((*regionChars) != '\0' && i < sizeof(region)/sizeof(region[0])) {
189*d57664e9SAndroid Build Coastguard Worker region[i++] = toupper(*regionChars);
190*d57664e9SAndroid Build Coastguard Worker regionChars++;
191*d57664e9SAndroid Build Coastguard Worker }
192*d57664e9SAndroid Build Coastguard Worker }
193*d57664e9SAndroid Build Coastguard Worker
setScript(const char * scriptChars)194*d57664e9SAndroid Build Coastguard Worker void AaptLocaleValue::setScript(const char* scriptChars) {
195*d57664e9SAndroid Build Coastguard Worker size_t i = 0;
196*d57664e9SAndroid Build Coastguard Worker while ((*scriptChars) != '\0' && i < sizeof(script)/sizeof(script[0])) {
197*d57664e9SAndroid Build Coastguard Worker if (i == 0) {
198*d57664e9SAndroid Build Coastguard Worker script[i++] = toupper(*scriptChars);
199*d57664e9SAndroid Build Coastguard Worker } else {
200*d57664e9SAndroid Build Coastguard Worker script[i++] = tolower(*scriptChars);
201*d57664e9SAndroid Build Coastguard Worker }
202*d57664e9SAndroid Build Coastguard Worker scriptChars++;
203*d57664e9SAndroid Build Coastguard Worker }
204*d57664e9SAndroid Build Coastguard Worker }
205*d57664e9SAndroid Build Coastguard Worker
setVariant(const char * variantChars)206*d57664e9SAndroid Build Coastguard Worker void AaptLocaleValue::setVariant(const char* variantChars) {
207*d57664e9SAndroid Build Coastguard Worker size_t i = 0;
208*d57664e9SAndroid Build Coastguard Worker while ((*variantChars) != '\0' && i < sizeof(variant)/sizeof(variant[0])) {
209*d57664e9SAndroid Build Coastguard Worker variant[i++] = *variantChars;
210*d57664e9SAndroid Build Coastguard Worker variantChars++;
211*d57664e9SAndroid Build Coastguard Worker }
212*d57664e9SAndroid Build Coastguard Worker }
213*d57664e9SAndroid Build Coastguard Worker
initFromFilterString(const String8 & str)214*d57664e9SAndroid Build Coastguard Worker bool AaptLocaleValue::initFromFilterString(const String8& str) {
215*d57664e9SAndroid Build Coastguard Worker // A locale (as specified in the filter) is an underscore separated name such
216*d57664e9SAndroid Build Coastguard Worker // as "en_US", "en_Latn_US", or "en_US_POSIX".
217*d57664e9SAndroid Build Coastguard Worker Vector<String8> parts = AaptUtil::splitAndLowerCase(str, '_');
218*d57664e9SAndroid Build Coastguard Worker
219*d57664e9SAndroid Build Coastguard Worker const int numTags = parts.size();
220*d57664e9SAndroid Build Coastguard Worker bool valid = false;
221*d57664e9SAndroid Build Coastguard Worker if (numTags >= 1) {
222*d57664e9SAndroid Build Coastguard Worker const String8& lang = parts[0];
223*d57664e9SAndroid Build Coastguard Worker if (isAlpha(lang) && (lang.length() == 2 || lang.length() == 3)) {
224*d57664e9SAndroid Build Coastguard Worker setLanguage(lang.c_str());
225*d57664e9SAndroid Build Coastguard Worker valid = true;
226*d57664e9SAndroid Build Coastguard Worker }
227*d57664e9SAndroid Build Coastguard Worker }
228*d57664e9SAndroid Build Coastguard Worker
229*d57664e9SAndroid Build Coastguard Worker if (!valid || numTags == 1) {
230*d57664e9SAndroid Build Coastguard Worker return valid;
231*d57664e9SAndroid Build Coastguard Worker }
232*d57664e9SAndroid Build Coastguard Worker
233*d57664e9SAndroid Build Coastguard Worker // At this point, valid == true && numTags > 1.
234*d57664e9SAndroid Build Coastguard Worker const String8& part2 = parts[1];
235*d57664e9SAndroid Build Coastguard Worker if ((part2.length() == 2 && isAlpha(part2)) ||
236*d57664e9SAndroid Build Coastguard Worker (part2.length() == 3 && isNumber(part2))) {
237*d57664e9SAndroid Build Coastguard Worker setRegion(part2.c_str());
238*d57664e9SAndroid Build Coastguard Worker } else if (part2.length() == 4 && isAlpha(part2)) {
239*d57664e9SAndroid Build Coastguard Worker setScript(part2.c_str());
240*d57664e9SAndroid Build Coastguard Worker } else if (part2.length() >= 4 && part2.length() <= 8) {
241*d57664e9SAndroid Build Coastguard Worker setVariant(part2.c_str());
242*d57664e9SAndroid Build Coastguard Worker } else {
243*d57664e9SAndroid Build Coastguard Worker valid = false;
244*d57664e9SAndroid Build Coastguard Worker }
245*d57664e9SAndroid Build Coastguard Worker
246*d57664e9SAndroid Build Coastguard Worker if (!valid || numTags == 2) {
247*d57664e9SAndroid Build Coastguard Worker return valid;
248*d57664e9SAndroid Build Coastguard Worker }
249*d57664e9SAndroid Build Coastguard Worker
250*d57664e9SAndroid Build Coastguard Worker // At this point, valid == true && numTags > 1.
251*d57664e9SAndroid Build Coastguard Worker const String8& part3 = parts[2];
252*d57664e9SAndroid Build Coastguard Worker if (((part3.length() == 2 && isAlpha(part3)) ||
253*d57664e9SAndroid Build Coastguard Worker (part3.length() == 3 && isNumber(part3))) && script[0]) {
254*d57664e9SAndroid Build Coastguard Worker setRegion(part3.c_str());
255*d57664e9SAndroid Build Coastguard Worker } else if (part3.length() >= 4 && part3.length() <= 8) {
256*d57664e9SAndroid Build Coastguard Worker setVariant(part3.c_str());
257*d57664e9SAndroid Build Coastguard Worker } else {
258*d57664e9SAndroid Build Coastguard Worker valid = false;
259*d57664e9SAndroid Build Coastguard Worker }
260*d57664e9SAndroid Build Coastguard Worker
261*d57664e9SAndroid Build Coastguard Worker if (!valid || numTags == 3) {
262*d57664e9SAndroid Build Coastguard Worker return valid;
263*d57664e9SAndroid Build Coastguard Worker }
264*d57664e9SAndroid Build Coastguard Worker
265*d57664e9SAndroid Build Coastguard Worker const String8& part4 = parts[3];
266*d57664e9SAndroid Build Coastguard Worker if (part4.length() >= 4 && part4.length() <= 8) {
267*d57664e9SAndroid Build Coastguard Worker setVariant(part4.c_str());
268*d57664e9SAndroid Build Coastguard Worker } else {
269*d57664e9SAndroid Build Coastguard Worker valid = false;
270*d57664e9SAndroid Build Coastguard Worker }
271*d57664e9SAndroid Build Coastguard Worker
272*d57664e9SAndroid Build Coastguard Worker if (!valid || numTags > 4) {
273*d57664e9SAndroid Build Coastguard Worker return false;
274*d57664e9SAndroid Build Coastguard Worker }
275*d57664e9SAndroid Build Coastguard Worker
276*d57664e9SAndroid Build Coastguard Worker return true;
277*d57664e9SAndroid Build Coastguard Worker }
278*d57664e9SAndroid Build Coastguard Worker
initFromDirName(const Vector<String8> & parts,const int startIndex)279*d57664e9SAndroid Build Coastguard Worker int AaptLocaleValue::initFromDirName(const Vector<String8>& parts, const int startIndex) {
280*d57664e9SAndroid Build Coastguard Worker const int size = parts.size();
281*d57664e9SAndroid Build Coastguard Worker int currentIndex = startIndex;
282*d57664e9SAndroid Build Coastguard Worker
283*d57664e9SAndroid Build Coastguard Worker String8 part = parts[currentIndex];
284*d57664e9SAndroid Build Coastguard Worker if (part[0] == 'b' && part[1] == '+') {
285*d57664e9SAndroid Build Coastguard Worker // This is a "modified" BCP 47 language tag. Same semantics as BCP 47 tags,
286*d57664e9SAndroid Build Coastguard Worker // except that the separator is "+" and not "-".
287*d57664e9SAndroid Build Coastguard Worker Vector<String8> subtags = AaptUtil::splitAndLowerCase(part, '+');
288*d57664e9SAndroid Build Coastguard Worker subtags.removeItemsAt(0);
289*d57664e9SAndroid Build Coastguard Worker if (subtags.size() == 1) {
290*d57664e9SAndroid Build Coastguard Worker setLanguage(subtags[0].c_str());
291*d57664e9SAndroid Build Coastguard Worker } else if (subtags.size() == 2) {
292*d57664e9SAndroid Build Coastguard Worker setLanguage(subtags[0].c_str());
293*d57664e9SAndroid Build Coastguard Worker
294*d57664e9SAndroid Build Coastguard Worker // The second tag can either be a region, a variant or a script.
295*d57664e9SAndroid Build Coastguard Worker switch (subtags[1].size()) {
296*d57664e9SAndroid Build Coastguard Worker case 2:
297*d57664e9SAndroid Build Coastguard Worker case 3:
298*d57664e9SAndroid Build Coastguard Worker setRegion(subtags[1].c_str());
299*d57664e9SAndroid Build Coastguard Worker break;
300*d57664e9SAndroid Build Coastguard Worker case 4:
301*d57664e9SAndroid Build Coastguard Worker if (isAlpha(subtags[1])) {
302*d57664e9SAndroid Build Coastguard Worker setScript(subtags[1].c_str());
303*d57664e9SAndroid Build Coastguard Worker break;
304*d57664e9SAndroid Build Coastguard Worker }
305*d57664e9SAndroid Build Coastguard Worker // This is not alphabetical, so we fall through to variant
306*d57664e9SAndroid Build Coastguard Worker [[fallthrough]];
307*d57664e9SAndroid Build Coastguard Worker case 5:
308*d57664e9SAndroid Build Coastguard Worker case 6:
309*d57664e9SAndroid Build Coastguard Worker case 7:
310*d57664e9SAndroid Build Coastguard Worker case 8:
311*d57664e9SAndroid Build Coastguard Worker setVariant(subtags[1].c_str());
312*d57664e9SAndroid Build Coastguard Worker break;
313*d57664e9SAndroid Build Coastguard Worker default:
314*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "ERROR: Invalid BCP 47 tag in directory name %s\n",
315*d57664e9SAndroid Build Coastguard Worker part.c_str());
316*d57664e9SAndroid Build Coastguard Worker return -1;
317*d57664e9SAndroid Build Coastguard Worker }
318*d57664e9SAndroid Build Coastguard Worker } else if (subtags.size() == 3) {
319*d57664e9SAndroid Build Coastguard Worker // The language is always the first subtag.
320*d57664e9SAndroid Build Coastguard Worker setLanguage(subtags[0].c_str());
321*d57664e9SAndroid Build Coastguard Worker
322*d57664e9SAndroid Build Coastguard Worker // The second subtag can either be a script or a region code.
323*d57664e9SAndroid Build Coastguard Worker // If its size is 4, it's a script code, else it's a region code.
324*d57664e9SAndroid Build Coastguard Worker if (subtags[1].size() == 4) {
325*d57664e9SAndroid Build Coastguard Worker setScript(subtags[1].c_str());
326*d57664e9SAndroid Build Coastguard Worker } else if (subtags[1].size() == 2 || subtags[1].size() == 3) {
327*d57664e9SAndroid Build Coastguard Worker setRegion(subtags[1].c_str());
328*d57664e9SAndroid Build Coastguard Worker } else {
329*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "ERROR: Invalid BCP 47 tag in directory name %s\n", part.c_str());
330*d57664e9SAndroid Build Coastguard Worker return -1;
331*d57664e9SAndroid Build Coastguard Worker }
332*d57664e9SAndroid Build Coastguard Worker
333*d57664e9SAndroid Build Coastguard Worker // The third tag can either be a region code (if the second tag was
334*d57664e9SAndroid Build Coastguard Worker // a script), else a variant code.
335*d57664e9SAndroid Build Coastguard Worker if (subtags[2].size() >= 4) {
336*d57664e9SAndroid Build Coastguard Worker setVariant(subtags[2].c_str());
337*d57664e9SAndroid Build Coastguard Worker } else {
338*d57664e9SAndroid Build Coastguard Worker setRegion(subtags[2].c_str());
339*d57664e9SAndroid Build Coastguard Worker }
340*d57664e9SAndroid Build Coastguard Worker } else if (subtags.size() == 4) {
341*d57664e9SAndroid Build Coastguard Worker setLanguage(subtags[0].c_str());
342*d57664e9SAndroid Build Coastguard Worker setScript(subtags[1].c_str());
343*d57664e9SAndroid Build Coastguard Worker setRegion(subtags[2].c_str());
344*d57664e9SAndroid Build Coastguard Worker setVariant(subtags[3].c_str());
345*d57664e9SAndroid Build Coastguard Worker } else {
346*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "ERROR: Invalid BCP 47 tag in directory name: %s\n", part.c_str());
347*d57664e9SAndroid Build Coastguard Worker return -1;
348*d57664e9SAndroid Build Coastguard Worker }
349*d57664e9SAndroid Build Coastguard Worker
350*d57664e9SAndroid Build Coastguard Worker return ++currentIndex;
351*d57664e9SAndroid Build Coastguard Worker } else {
352*d57664e9SAndroid Build Coastguard Worker if ((part.length() == 2 || part.length() == 3)
353*d57664e9SAndroid Build Coastguard Worker && isAlpha(part) && strcmp("car", part.c_str())) {
354*d57664e9SAndroid Build Coastguard Worker setLanguage(part.c_str());
355*d57664e9SAndroid Build Coastguard Worker if (++currentIndex == size) {
356*d57664e9SAndroid Build Coastguard Worker return size;
357*d57664e9SAndroid Build Coastguard Worker }
358*d57664e9SAndroid Build Coastguard Worker } else {
359*d57664e9SAndroid Build Coastguard Worker return currentIndex;
360*d57664e9SAndroid Build Coastguard Worker }
361*d57664e9SAndroid Build Coastguard Worker
362*d57664e9SAndroid Build Coastguard Worker part = parts[currentIndex];
363*d57664e9SAndroid Build Coastguard Worker if (part.c_str()[0] == 'r' && part.length() == 3) {
364*d57664e9SAndroid Build Coastguard Worker setRegion(part.c_str() + 1);
365*d57664e9SAndroid Build Coastguard Worker if (++currentIndex == size) {
366*d57664e9SAndroid Build Coastguard Worker return size;
367*d57664e9SAndroid Build Coastguard Worker }
368*d57664e9SAndroid Build Coastguard Worker }
369*d57664e9SAndroid Build Coastguard Worker }
370*d57664e9SAndroid Build Coastguard Worker
371*d57664e9SAndroid Build Coastguard Worker return currentIndex;
372*d57664e9SAndroid Build Coastguard Worker }
373*d57664e9SAndroid Build Coastguard Worker
initFromResTable(const ResTable_config & config)374*d57664e9SAndroid Build Coastguard Worker void AaptLocaleValue::initFromResTable(const ResTable_config& config) {
375*d57664e9SAndroid Build Coastguard Worker config.unpackLanguage(language);
376*d57664e9SAndroid Build Coastguard Worker config.unpackRegion(region);
377*d57664e9SAndroid Build Coastguard Worker if (config.localeScript[0] && !config.localeScriptWasComputed) {
378*d57664e9SAndroid Build Coastguard Worker memcpy(script, config.localeScript, sizeof(config.localeScript));
379*d57664e9SAndroid Build Coastguard Worker }
380*d57664e9SAndroid Build Coastguard Worker
381*d57664e9SAndroid Build Coastguard Worker if (config.localeVariant[0]) {
382*d57664e9SAndroid Build Coastguard Worker memcpy(variant, config.localeVariant, sizeof(config.localeVariant));
383*d57664e9SAndroid Build Coastguard Worker }
384*d57664e9SAndroid Build Coastguard Worker }
385*d57664e9SAndroid Build Coastguard Worker
writeTo(ResTable_config * out) const386*d57664e9SAndroid Build Coastguard Worker void AaptLocaleValue::writeTo(ResTable_config* out) const {
387*d57664e9SAndroid Build Coastguard Worker out->packLanguage(language);
388*d57664e9SAndroid Build Coastguard Worker out->packRegion(region);
389*d57664e9SAndroid Build Coastguard Worker
390*d57664e9SAndroid Build Coastguard Worker if (script[0]) {
391*d57664e9SAndroid Build Coastguard Worker memcpy(out->localeScript, script, sizeof(out->localeScript));
392*d57664e9SAndroid Build Coastguard Worker }
393*d57664e9SAndroid Build Coastguard Worker
394*d57664e9SAndroid Build Coastguard Worker if (variant[0]) {
395*d57664e9SAndroid Build Coastguard Worker memcpy(out->localeVariant, variant, sizeof(out->localeVariant));
396*d57664e9SAndroid Build Coastguard Worker }
397*d57664e9SAndroid Build Coastguard Worker }
398*d57664e9SAndroid Build Coastguard Worker
399*d57664e9SAndroid Build Coastguard Worker bool
initFromDirName(const char * dir,String8 * resType)400*d57664e9SAndroid Build Coastguard Worker AaptGroupEntry::initFromDirName(const char* dir, String8* resType)
401*d57664e9SAndroid Build Coastguard Worker {
402*d57664e9SAndroid Build Coastguard Worker const char* q = strchr(dir, '-');
403*d57664e9SAndroid Build Coastguard Worker size_t typeLen;
404*d57664e9SAndroid Build Coastguard Worker if (q != NULL) {
405*d57664e9SAndroid Build Coastguard Worker typeLen = q - dir;
406*d57664e9SAndroid Build Coastguard Worker } else {
407*d57664e9SAndroid Build Coastguard Worker typeLen = strlen(dir);
408*d57664e9SAndroid Build Coastguard Worker }
409*d57664e9SAndroid Build Coastguard Worker
410*d57664e9SAndroid Build Coastguard Worker String8 type(dir, typeLen);
411*d57664e9SAndroid Build Coastguard Worker if (!isValidResourceType(type)) {
412*d57664e9SAndroid Build Coastguard Worker return false;
413*d57664e9SAndroid Build Coastguard Worker }
414*d57664e9SAndroid Build Coastguard Worker
415*d57664e9SAndroid Build Coastguard Worker if (q != NULL) {
416*d57664e9SAndroid Build Coastguard Worker if (!AaptConfig::parse(String8(q + 1), &mParams)) {
417*d57664e9SAndroid Build Coastguard Worker return false;
418*d57664e9SAndroid Build Coastguard Worker }
419*d57664e9SAndroid Build Coastguard Worker }
420*d57664e9SAndroid Build Coastguard Worker
421*d57664e9SAndroid Build Coastguard Worker *resType = type;
422*d57664e9SAndroid Build Coastguard Worker return true;
423*d57664e9SAndroid Build Coastguard Worker }
424*d57664e9SAndroid Build Coastguard Worker
425*d57664e9SAndroid Build Coastguard Worker String8
toDirName(const String8 & resType) const426*d57664e9SAndroid Build Coastguard Worker AaptGroupEntry::toDirName(const String8& resType) const
427*d57664e9SAndroid Build Coastguard Worker {
428*d57664e9SAndroid Build Coastguard Worker String8 s = resType;
429*d57664e9SAndroid Build Coastguard Worker String8 params = mParams.toString();
430*d57664e9SAndroid Build Coastguard Worker if (params.length() > 0) {
431*d57664e9SAndroid Build Coastguard Worker if (s.length() > 0) {
432*d57664e9SAndroid Build Coastguard Worker s += "-";
433*d57664e9SAndroid Build Coastguard Worker }
434*d57664e9SAndroid Build Coastguard Worker s += params;
435*d57664e9SAndroid Build Coastguard Worker }
436*d57664e9SAndroid Build Coastguard Worker return s;
437*d57664e9SAndroid Build Coastguard Worker }
438*d57664e9SAndroid Build Coastguard Worker
439*d57664e9SAndroid Build Coastguard Worker
440*d57664e9SAndroid Build Coastguard Worker // =========================================================================
441*d57664e9SAndroid Build Coastguard Worker // =========================================================================
442*d57664e9SAndroid Build Coastguard Worker // =========================================================================
443*d57664e9SAndroid Build Coastguard Worker
editData(size_t size)444*d57664e9SAndroid Build Coastguard Worker void* AaptFile::editData(size_t size)
445*d57664e9SAndroid Build Coastguard Worker {
446*d57664e9SAndroid Build Coastguard Worker if (size <= mBufferSize) {
447*d57664e9SAndroid Build Coastguard Worker mDataSize = size;
448*d57664e9SAndroid Build Coastguard Worker return mData;
449*d57664e9SAndroid Build Coastguard Worker }
450*d57664e9SAndroid Build Coastguard Worker size_t allocSize = (size*3)/2;
451*d57664e9SAndroid Build Coastguard Worker void* buf = realloc(mData, allocSize);
452*d57664e9SAndroid Build Coastguard Worker if (buf == NULL) {
453*d57664e9SAndroid Build Coastguard Worker return NULL;
454*d57664e9SAndroid Build Coastguard Worker }
455*d57664e9SAndroid Build Coastguard Worker mData = buf;
456*d57664e9SAndroid Build Coastguard Worker mDataSize = size;
457*d57664e9SAndroid Build Coastguard Worker mBufferSize = allocSize;
458*d57664e9SAndroid Build Coastguard Worker return buf;
459*d57664e9SAndroid Build Coastguard Worker }
460*d57664e9SAndroid Build Coastguard Worker
editDataInRange(size_t offset,size_t size)461*d57664e9SAndroid Build Coastguard Worker void* AaptFile::editDataInRange(size_t offset, size_t size)
462*d57664e9SAndroid Build Coastguard Worker {
463*d57664e9SAndroid Build Coastguard Worker return (void*)(((uint8_t*) editData(offset + size)) + offset);
464*d57664e9SAndroid Build Coastguard Worker }
465*d57664e9SAndroid Build Coastguard Worker
editData(size_t * outSize)466*d57664e9SAndroid Build Coastguard Worker void* AaptFile::editData(size_t* outSize)
467*d57664e9SAndroid Build Coastguard Worker {
468*d57664e9SAndroid Build Coastguard Worker if (outSize) {
469*d57664e9SAndroid Build Coastguard Worker *outSize = mDataSize;
470*d57664e9SAndroid Build Coastguard Worker }
471*d57664e9SAndroid Build Coastguard Worker return mData;
472*d57664e9SAndroid Build Coastguard Worker }
473*d57664e9SAndroid Build Coastguard Worker
padData(size_t wordSize)474*d57664e9SAndroid Build Coastguard Worker void* AaptFile::padData(size_t wordSize)
475*d57664e9SAndroid Build Coastguard Worker {
476*d57664e9SAndroid Build Coastguard Worker const size_t extra = mDataSize%wordSize;
477*d57664e9SAndroid Build Coastguard Worker if (extra == 0) {
478*d57664e9SAndroid Build Coastguard Worker return mData;
479*d57664e9SAndroid Build Coastguard Worker }
480*d57664e9SAndroid Build Coastguard Worker
481*d57664e9SAndroid Build Coastguard Worker size_t initial = mDataSize;
482*d57664e9SAndroid Build Coastguard Worker void* data = editData(initial+(wordSize-extra));
483*d57664e9SAndroid Build Coastguard Worker if (data != NULL) {
484*d57664e9SAndroid Build Coastguard Worker memset(((uint8_t*)data) + initial, 0, wordSize-extra);
485*d57664e9SAndroid Build Coastguard Worker }
486*d57664e9SAndroid Build Coastguard Worker return data;
487*d57664e9SAndroid Build Coastguard Worker }
488*d57664e9SAndroid Build Coastguard Worker
writeData(const void * data,size_t size)489*d57664e9SAndroid Build Coastguard Worker status_t AaptFile::writeData(const void* data, size_t size)
490*d57664e9SAndroid Build Coastguard Worker {
491*d57664e9SAndroid Build Coastguard Worker size_t end = mDataSize;
492*d57664e9SAndroid Build Coastguard Worker size_t total = size + end;
493*d57664e9SAndroid Build Coastguard Worker void* buf = editData(total);
494*d57664e9SAndroid Build Coastguard Worker if (buf == NULL) {
495*d57664e9SAndroid Build Coastguard Worker return UNKNOWN_ERROR;
496*d57664e9SAndroid Build Coastguard Worker }
497*d57664e9SAndroid Build Coastguard Worker memcpy(((char*)buf)+end, data, size);
498*d57664e9SAndroid Build Coastguard Worker return NO_ERROR;
499*d57664e9SAndroid Build Coastguard Worker }
500*d57664e9SAndroid Build Coastguard Worker
clearData()501*d57664e9SAndroid Build Coastguard Worker void AaptFile::clearData()
502*d57664e9SAndroid Build Coastguard Worker {
503*d57664e9SAndroid Build Coastguard Worker if (mData != NULL) free(mData);
504*d57664e9SAndroid Build Coastguard Worker mData = NULL;
505*d57664e9SAndroid Build Coastguard Worker mDataSize = 0;
506*d57664e9SAndroid Build Coastguard Worker mBufferSize = 0;
507*d57664e9SAndroid Build Coastguard Worker }
508*d57664e9SAndroid Build Coastguard Worker
getPrintableSource() const509*d57664e9SAndroid Build Coastguard Worker String8 AaptFile::getPrintableSource() const
510*d57664e9SAndroid Build Coastguard Worker {
511*d57664e9SAndroid Build Coastguard Worker if (hasData()) {
512*d57664e9SAndroid Build Coastguard Worker String8 name(mGroupEntry.toDirName(String8()));
513*d57664e9SAndroid Build Coastguard Worker appendPath(name, mPath);
514*d57664e9SAndroid Build Coastguard Worker name.append(" #generated");
515*d57664e9SAndroid Build Coastguard Worker return name;
516*d57664e9SAndroid Build Coastguard Worker }
517*d57664e9SAndroid Build Coastguard Worker return mSourceFile;
518*d57664e9SAndroid Build Coastguard Worker }
519*d57664e9SAndroid Build Coastguard Worker
520*d57664e9SAndroid Build Coastguard Worker // =========================================================================
521*d57664e9SAndroid Build Coastguard Worker // =========================================================================
522*d57664e9SAndroid Build Coastguard Worker // =========================================================================
523*d57664e9SAndroid Build Coastguard Worker
addFile(const sp<AaptFile> & file,const bool overwriteDuplicate)524*d57664e9SAndroid Build Coastguard Worker status_t AaptGroup::addFile(const sp<AaptFile>& file, const bool overwriteDuplicate)
525*d57664e9SAndroid Build Coastguard Worker {
526*d57664e9SAndroid Build Coastguard Worker ssize_t index = mFiles.indexOfKey(file->getGroupEntry());
527*d57664e9SAndroid Build Coastguard Worker if (index >= 0 && overwriteDuplicate) {
528*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "warning: overwriting '%s' with '%s'\n",
529*d57664e9SAndroid Build Coastguard Worker mFiles[index]->getSourceFile().c_str(),
530*d57664e9SAndroid Build Coastguard Worker file->getSourceFile().c_str());
531*d57664e9SAndroid Build Coastguard Worker removeFile(index);
532*d57664e9SAndroid Build Coastguard Worker index = -1;
533*d57664e9SAndroid Build Coastguard Worker }
534*d57664e9SAndroid Build Coastguard Worker
535*d57664e9SAndroid Build Coastguard Worker if (index < 0) {
536*d57664e9SAndroid Build Coastguard Worker file->mPath = mPath;
537*d57664e9SAndroid Build Coastguard Worker mFiles.add(file->getGroupEntry(), file);
538*d57664e9SAndroid Build Coastguard Worker return NO_ERROR;
539*d57664e9SAndroid Build Coastguard Worker }
540*d57664e9SAndroid Build Coastguard Worker
541*d57664e9SAndroid Build Coastguard Worker // Check if the version is automatically applied. This is a common source of
542*d57664e9SAndroid Build Coastguard Worker // error.
543*d57664e9SAndroid Build Coastguard Worker ConfigDescription withoutVersion = file->getGroupEntry().toParams();
544*d57664e9SAndroid Build Coastguard Worker withoutVersion.version = 0;
545*d57664e9SAndroid Build Coastguard Worker AaptConfig::applyVersionForCompatibility(&withoutVersion);
546*d57664e9SAndroid Build Coastguard Worker
547*d57664e9SAndroid Build Coastguard Worker const sp<AaptFile>& originalFile = mFiles.valueAt(index);
548*d57664e9SAndroid Build Coastguard Worker SourcePos(file->getSourceFile(), -1)
549*d57664e9SAndroid Build Coastguard Worker .error("Duplicate file.\n%s: Original is here. %s",
550*d57664e9SAndroid Build Coastguard Worker originalFile->getPrintableSource().c_str(),
551*d57664e9SAndroid Build Coastguard Worker (withoutVersion.version != 0) ? "The version qualifier may be implied." : "");
552*d57664e9SAndroid Build Coastguard Worker return UNKNOWN_ERROR;
553*d57664e9SAndroid Build Coastguard Worker }
554*d57664e9SAndroid Build Coastguard Worker
removeFile(size_t index)555*d57664e9SAndroid Build Coastguard Worker void AaptGroup::removeFile(size_t index)
556*d57664e9SAndroid Build Coastguard Worker {
557*d57664e9SAndroid Build Coastguard Worker mFiles.removeItemsAt(index);
558*d57664e9SAndroid Build Coastguard Worker }
559*d57664e9SAndroid Build Coastguard Worker
print(const String8 & prefix) const560*d57664e9SAndroid Build Coastguard Worker void AaptGroup::print(const String8& prefix) const
561*d57664e9SAndroid Build Coastguard Worker {
562*d57664e9SAndroid Build Coastguard Worker printf("%s%s\n", prefix.c_str(), getPath().c_str());
563*d57664e9SAndroid Build Coastguard Worker const size_t N=mFiles.size();
564*d57664e9SAndroid Build Coastguard Worker size_t i;
565*d57664e9SAndroid Build Coastguard Worker for (i=0; i<N; i++) {
566*d57664e9SAndroid Build Coastguard Worker sp<AaptFile> file = mFiles.valueAt(i);
567*d57664e9SAndroid Build Coastguard Worker const AaptGroupEntry& e = file->getGroupEntry();
568*d57664e9SAndroid Build Coastguard Worker if (file->hasData()) {
569*d57664e9SAndroid Build Coastguard Worker printf("%s Gen: (%s) %d bytes\n", prefix.c_str(), e.toDirName(String8()).c_str(),
570*d57664e9SAndroid Build Coastguard Worker (int)file->getSize());
571*d57664e9SAndroid Build Coastguard Worker } else {
572*d57664e9SAndroid Build Coastguard Worker printf("%s Src: (%s) %s\n", prefix.c_str(), e.toDirName(String8()).c_str(),
573*d57664e9SAndroid Build Coastguard Worker file->getPrintableSource().c_str());
574*d57664e9SAndroid Build Coastguard Worker }
575*d57664e9SAndroid Build Coastguard Worker //printf("%s File Group Entry: %s\n", prefix.c_str(),
576*d57664e9SAndroid Build Coastguard Worker // file->getGroupEntry().toDirName(String8()).c_str());
577*d57664e9SAndroid Build Coastguard Worker }
578*d57664e9SAndroid Build Coastguard Worker }
579*d57664e9SAndroid Build Coastguard Worker
getPrintableSource() const580*d57664e9SAndroid Build Coastguard Worker String8 AaptGroup::getPrintableSource() const
581*d57664e9SAndroid Build Coastguard Worker {
582*d57664e9SAndroid Build Coastguard Worker if (mFiles.size() > 0) {
583*d57664e9SAndroid Build Coastguard Worker // Arbitrarily pull the first source file out of the list.
584*d57664e9SAndroid Build Coastguard Worker return mFiles.valueAt(0)->getPrintableSource();
585*d57664e9SAndroid Build Coastguard Worker }
586*d57664e9SAndroid Build Coastguard Worker
587*d57664e9SAndroid Build Coastguard Worker // Should never hit this case, but to be safe...
588*d57664e9SAndroid Build Coastguard Worker return getPath();
589*d57664e9SAndroid Build Coastguard Worker
590*d57664e9SAndroid Build Coastguard Worker }
591*d57664e9SAndroid Build Coastguard Worker
592*d57664e9SAndroid Build Coastguard Worker // =========================================================================
593*d57664e9SAndroid Build Coastguard Worker // =========================================================================
594*d57664e9SAndroid Build Coastguard Worker // =========================================================================
595*d57664e9SAndroid Build Coastguard Worker
addFile(const String8 & name,const sp<AaptGroup> & file)596*d57664e9SAndroid Build Coastguard Worker status_t AaptDir::addFile(const String8& name, const sp<AaptGroup>& file)
597*d57664e9SAndroid Build Coastguard Worker {
598*d57664e9SAndroid Build Coastguard Worker if (mFiles.indexOfKey(name) >= 0) {
599*d57664e9SAndroid Build Coastguard Worker return ALREADY_EXISTS;
600*d57664e9SAndroid Build Coastguard Worker }
601*d57664e9SAndroid Build Coastguard Worker mFiles.add(name, file);
602*d57664e9SAndroid Build Coastguard Worker return NO_ERROR;
603*d57664e9SAndroid Build Coastguard Worker }
604*d57664e9SAndroid Build Coastguard Worker
addDir(const String8 & name,const sp<AaptDir> & dir)605*d57664e9SAndroid Build Coastguard Worker status_t AaptDir::addDir(const String8& name, const sp<AaptDir>& dir)
606*d57664e9SAndroid Build Coastguard Worker {
607*d57664e9SAndroid Build Coastguard Worker if (mDirs.indexOfKey(name) >= 0) {
608*d57664e9SAndroid Build Coastguard Worker return ALREADY_EXISTS;
609*d57664e9SAndroid Build Coastguard Worker }
610*d57664e9SAndroid Build Coastguard Worker mDirs.add(name, dir);
611*d57664e9SAndroid Build Coastguard Worker return NO_ERROR;
612*d57664e9SAndroid Build Coastguard Worker }
613*d57664e9SAndroid Build Coastguard Worker
makeDir(const String8 & path)614*d57664e9SAndroid Build Coastguard Worker sp<AaptDir> AaptDir::makeDir(const String8& path)
615*d57664e9SAndroid Build Coastguard Worker {
616*d57664e9SAndroid Build Coastguard Worker String8 name;
617*d57664e9SAndroid Build Coastguard Worker String8 remain = path;
618*d57664e9SAndroid Build Coastguard Worker
619*d57664e9SAndroid Build Coastguard Worker sp<AaptDir> subdir = this;
620*d57664e9SAndroid Build Coastguard Worker while (name = walkPath(remain, &remain), remain != "") {
621*d57664e9SAndroid Build Coastguard Worker subdir = subdir->makeDir(name);
622*d57664e9SAndroid Build Coastguard Worker }
623*d57664e9SAndroid Build Coastguard Worker
624*d57664e9SAndroid Build Coastguard Worker ssize_t i = subdir->mDirs.indexOfKey(name);
625*d57664e9SAndroid Build Coastguard Worker if (i >= 0) {
626*d57664e9SAndroid Build Coastguard Worker return subdir->mDirs.valueAt(i);
627*d57664e9SAndroid Build Coastguard Worker }
628*d57664e9SAndroid Build Coastguard Worker sp<AaptDir> dir = new AaptDir(name, appendPathCopy(subdir->mPath, name));
629*d57664e9SAndroid Build Coastguard Worker subdir->mDirs.add(name, dir);
630*d57664e9SAndroid Build Coastguard Worker return dir;
631*d57664e9SAndroid Build Coastguard Worker }
632*d57664e9SAndroid Build Coastguard Worker
removeFile(const String8 & name)633*d57664e9SAndroid Build Coastguard Worker void AaptDir::removeFile(const String8& name)
634*d57664e9SAndroid Build Coastguard Worker {
635*d57664e9SAndroid Build Coastguard Worker mFiles.removeItem(name);
636*d57664e9SAndroid Build Coastguard Worker }
637*d57664e9SAndroid Build Coastguard Worker
removeDir(const String8 & name)638*d57664e9SAndroid Build Coastguard Worker void AaptDir::removeDir(const String8& name)
639*d57664e9SAndroid Build Coastguard Worker {
640*d57664e9SAndroid Build Coastguard Worker mDirs.removeItem(name);
641*d57664e9SAndroid Build Coastguard Worker }
642*d57664e9SAndroid Build Coastguard Worker
addLeafFile(const String8 & leafName,const sp<AaptFile> & file,const bool overwrite)643*d57664e9SAndroid Build Coastguard Worker status_t AaptDir::addLeafFile(const String8& leafName, const sp<AaptFile>& file,
644*d57664e9SAndroid Build Coastguard Worker const bool overwrite)
645*d57664e9SAndroid Build Coastguard Worker {
646*d57664e9SAndroid Build Coastguard Worker sp<AaptGroup> group;
647*d57664e9SAndroid Build Coastguard Worker if (mFiles.indexOfKey(leafName) >= 0) {
648*d57664e9SAndroid Build Coastguard Worker group = mFiles.valueFor(leafName);
649*d57664e9SAndroid Build Coastguard Worker } else {
650*d57664e9SAndroid Build Coastguard Worker group = new AaptGroup(leafName, appendPathCopy(mPath, leafName));
651*d57664e9SAndroid Build Coastguard Worker mFiles.add(leafName, group);
652*d57664e9SAndroid Build Coastguard Worker }
653*d57664e9SAndroid Build Coastguard Worker
654*d57664e9SAndroid Build Coastguard Worker return group->addFile(file, overwrite);
655*d57664e9SAndroid Build Coastguard Worker }
656*d57664e9SAndroid Build Coastguard Worker
slurpFullTree(Bundle * bundle,const String8 & srcDir,const AaptGroupEntry & kind,const String8 & resType,sp<FilePathStore> & fullResPaths,const bool overwrite)657*d57664e9SAndroid Build Coastguard Worker ssize_t AaptDir::slurpFullTree(Bundle* bundle, const String8& srcDir,
658*d57664e9SAndroid Build Coastguard Worker const AaptGroupEntry& kind, const String8& resType,
659*d57664e9SAndroid Build Coastguard Worker sp<FilePathStore>& fullResPaths, const bool overwrite)
660*d57664e9SAndroid Build Coastguard Worker {
661*d57664e9SAndroid Build Coastguard Worker Vector<String8> fileNames;
662*d57664e9SAndroid Build Coastguard Worker {
663*d57664e9SAndroid Build Coastguard Worker DIR* dir = NULL;
664*d57664e9SAndroid Build Coastguard Worker
665*d57664e9SAndroid Build Coastguard Worker dir = opendir(srcDir.c_str());
666*d57664e9SAndroid Build Coastguard Worker if (dir == NULL) {
667*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "ERROR: opendir(%s): %s\n", srcDir.c_str(), strerror(errno));
668*d57664e9SAndroid Build Coastguard Worker return UNKNOWN_ERROR;
669*d57664e9SAndroid Build Coastguard Worker }
670*d57664e9SAndroid Build Coastguard Worker
671*d57664e9SAndroid Build Coastguard Worker /*
672*d57664e9SAndroid Build Coastguard Worker * Slurp the filenames out of the directory.
673*d57664e9SAndroid Build Coastguard Worker */
674*d57664e9SAndroid Build Coastguard Worker while (1) {
675*d57664e9SAndroid Build Coastguard Worker struct dirent* entry;
676*d57664e9SAndroid Build Coastguard Worker
677*d57664e9SAndroid Build Coastguard Worker entry = readdir(dir);
678*d57664e9SAndroid Build Coastguard Worker if (entry == NULL)
679*d57664e9SAndroid Build Coastguard Worker break;
680*d57664e9SAndroid Build Coastguard Worker
681*d57664e9SAndroid Build Coastguard Worker if (isHidden(srcDir.c_str(), entry->d_name))
682*d57664e9SAndroid Build Coastguard Worker continue;
683*d57664e9SAndroid Build Coastguard Worker
684*d57664e9SAndroid Build Coastguard Worker String8 name(entry->d_name);
685*d57664e9SAndroid Build Coastguard Worker fileNames.add(name);
686*d57664e9SAndroid Build Coastguard Worker // Add fully qualified path for dependency purposes
687*d57664e9SAndroid Build Coastguard Worker // if we're collecting them
688*d57664e9SAndroid Build Coastguard Worker if (fullResPaths != NULL) {
689*d57664e9SAndroid Build Coastguard Worker fullResPaths->add(appendPathCopy(srcDir, name));
690*d57664e9SAndroid Build Coastguard Worker }
691*d57664e9SAndroid Build Coastguard Worker }
692*d57664e9SAndroid Build Coastguard Worker closedir(dir);
693*d57664e9SAndroid Build Coastguard Worker }
694*d57664e9SAndroid Build Coastguard Worker
695*d57664e9SAndroid Build Coastguard Worker ssize_t count = 0;
696*d57664e9SAndroid Build Coastguard Worker
697*d57664e9SAndroid Build Coastguard Worker /*
698*d57664e9SAndroid Build Coastguard Worker * Stash away the files and recursively descend into subdirectories.
699*d57664e9SAndroid Build Coastguard Worker */
700*d57664e9SAndroid Build Coastguard Worker const size_t N = fileNames.size();
701*d57664e9SAndroid Build Coastguard Worker size_t i;
702*d57664e9SAndroid Build Coastguard Worker for (i = 0; i < N; i++) {
703*d57664e9SAndroid Build Coastguard Worker String8 pathName(srcDir);
704*d57664e9SAndroid Build Coastguard Worker FileType type;
705*d57664e9SAndroid Build Coastguard Worker
706*d57664e9SAndroid Build Coastguard Worker appendPath(pathName, fileNames[i]);
707*d57664e9SAndroid Build Coastguard Worker type = getFileType(pathName.c_str());
708*d57664e9SAndroid Build Coastguard Worker if (type == kFileTypeDirectory) {
709*d57664e9SAndroid Build Coastguard Worker sp<AaptDir> subdir;
710*d57664e9SAndroid Build Coastguard Worker bool notAdded = false;
711*d57664e9SAndroid Build Coastguard Worker if (mDirs.indexOfKey(fileNames[i]) >= 0) {
712*d57664e9SAndroid Build Coastguard Worker subdir = mDirs.valueFor(fileNames[i]);
713*d57664e9SAndroid Build Coastguard Worker } else {
714*d57664e9SAndroid Build Coastguard Worker subdir = new AaptDir(fileNames[i], appendPathCopy(mPath, fileNames[i]));
715*d57664e9SAndroid Build Coastguard Worker notAdded = true;
716*d57664e9SAndroid Build Coastguard Worker }
717*d57664e9SAndroid Build Coastguard Worker ssize_t res = subdir->slurpFullTree(bundle, pathName, kind,
718*d57664e9SAndroid Build Coastguard Worker resType, fullResPaths, overwrite);
719*d57664e9SAndroid Build Coastguard Worker if (res < NO_ERROR) {
720*d57664e9SAndroid Build Coastguard Worker return res;
721*d57664e9SAndroid Build Coastguard Worker }
722*d57664e9SAndroid Build Coastguard Worker if (res > 0 && notAdded) {
723*d57664e9SAndroid Build Coastguard Worker mDirs.add(fileNames[i], subdir);
724*d57664e9SAndroid Build Coastguard Worker }
725*d57664e9SAndroid Build Coastguard Worker count += res;
726*d57664e9SAndroid Build Coastguard Worker } else if (type == kFileTypeRegular) {
727*d57664e9SAndroid Build Coastguard Worker sp<AaptFile> file = new AaptFile(pathName, kind, resType);
728*d57664e9SAndroid Build Coastguard Worker status_t err = addLeafFile(fileNames[i], file, overwrite);
729*d57664e9SAndroid Build Coastguard Worker if (err != NO_ERROR) {
730*d57664e9SAndroid Build Coastguard Worker return err;
731*d57664e9SAndroid Build Coastguard Worker }
732*d57664e9SAndroid Build Coastguard Worker
733*d57664e9SAndroid Build Coastguard Worker count++;
734*d57664e9SAndroid Build Coastguard Worker
735*d57664e9SAndroid Build Coastguard Worker } else {
736*d57664e9SAndroid Build Coastguard Worker if (bundle->getVerbose())
737*d57664e9SAndroid Build Coastguard Worker printf(" (ignoring non-file/dir '%s')\n", pathName.c_str());
738*d57664e9SAndroid Build Coastguard Worker }
739*d57664e9SAndroid Build Coastguard Worker }
740*d57664e9SAndroid Build Coastguard Worker
741*d57664e9SAndroid Build Coastguard Worker return count;
742*d57664e9SAndroid Build Coastguard Worker }
743*d57664e9SAndroid Build Coastguard Worker
validate() const744*d57664e9SAndroid Build Coastguard Worker status_t AaptDir::validate() const
745*d57664e9SAndroid Build Coastguard Worker {
746*d57664e9SAndroid Build Coastguard Worker const size_t NF = mFiles.size();
747*d57664e9SAndroid Build Coastguard Worker const size_t ND = mDirs.size();
748*d57664e9SAndroid Build Coastguard Worker size_t i;
749*d57664e9SAndroid Build Coastguard Worker for (i = 0; i < NF; i++) {
750*d57664e9SAndroid Build Coastguard Worker if (!validateFileName(mFiles.valueAt(i)->getLeaf().c_str())) {
751*d57664e9SAndroid Build Coastguard Worker SourcePos(mFiles.valueAt(i)->getPrintableSource(), -1).error(
752*d57664e9SAndroid Build Coastguard Worker "Invalid filename. Unable to add.");
753*d57664e9SAndroid Build Coastguard Worker return UNKNOWN_ERROR;
754*d57664e9SAndroid Build Coastguard Worker }
755*d57664e9SAndroid Build Coastguard Worker
756*d57664e9SAndroid Build Coastguard Worker size_t j;
757*d57664e9SAndroid Build Coastguard Worker for (j = i+1; j < NF; j++) {
758*d57664e9SAndroid Build Coastguard Worker if (strcasecmp(mFiles.valueAt(i)->getLeaf().c_str(),
759*d57664e9SAndroid Build Coastguard Worker mFiles.valueAt(j)->getLeaf().c_str()) == 0) {
760*d57664e9SAndroid Build Coastguard Worker SourcePos(mFiles.valueAt(i)->getPrintableSource(), -1).error(
761*d57664e9SAndroid Build Coastguard Worker "File is case-insensitive equivalent to: %s",
762*d57664e9SAndroid Build Coastguard Worker mFiles.valueAt(j)->getPrintableSource().c_str());
763*d57664e9SAndroid Build Coastguard Worker return UNKNOWN_ERROR;
764*d57664e9SAndroid Build Coastguard Worker }
765*d57664e9SAndroid Build Coastguard Worker
766*d57664e9SAndroid Build Coastguard Worker // TODO: if ".gz", check for non-.gz; if non-, check for ".gz"
767*d57664e9SAndroid Build Coastguard Worker // (this is mostly caught by the "marked" stuff, below)
768*d57664e9SAndroid Build Coastguard Worker }
769*d57664e9SAndroid Build Coastguard Worker
770*d57664e9SAndroid Build Coastguard Worker for (j = 0; j < ND; j++) {
771*d57664e9SAndroid Build Coastguard Worker if (strcasecmp(mFiles.valueAt(i)->getLeaf().c_str(),
772*d57664e9SAndroid Build Coastguard Worker mDirs.valueAt(j)->getLeaf().c_str()) == 0) {
773*d57664e9SAndroid Build Coastguard Worker SourcePos(mFiles.valueAt(i)->getPrintableSource(), -1).error(
774*d57664e9SAndroid Build Coastguard Worker "File conflicts with dir from: %s",
775*d57664e9SAndroid Build Coastguard Worker mDirs.valueAt(j)->getPrintableSource().c_str());
776*d57664e9SAndroid Build Coastguard Worker return UNKNOWN_ERROR;
777*d57664e9SAndroid Build Coastguard Worker }
778*d57664e9SAndroid Build Coastguard Worker }
779*d57664e9SAndroid Build Coastguard Worker }
780*d57664e9SAndroid Build Coastguard Worker
781*d57664e9SAndroid Build Coastguard Worker for (i = 0; i < ND; i++) {
782*d57664e9SAndroid Build Coastguard Worker if (!validateFileName(mDirs.valueAt(i)->getLeaf().c_str())) {
783*d57664e9SAndroid Build Coastguard Worker SourcePos(mDirs.valueAt(i)->getPrintableSource(), -1).error(
784*d57664e9SAndroid Build Coastguard Worker "Invalid directory name, unable to add.");
785*d57664e9SAndroid Build Coastguard Worker return UNKNOWN_ERROR;
786*d57664e9SAndroid Build Coastguard Worker }
787*d57664e9SAndroid Build Coastguard Worker
788*d57664e9SAndroid Build Coastguard Worker size_t j;
789*d57664e9SAndroid Build Coastguard Worker for (j = i+1; j < ND; j++) {
790*d57664e9SAndroid Build Coastguard Worker if (strcasecmp(mDirs.valueAt(i)->getLeaf().c_str(),
791*d57664e9SAndroid Build Coastguard Worker mDirs.valueAt(j)->getLeaf().c_str()) == 0) {
792*d57664e9SAndroid Build Coastguard Worker SourcePos(mDirs.valueAt(i)->getPrintableSource(), -1).error(
793*d57664e9SAndroid Build Coastguard Worker "Directory is case-insensitive equivalent to: %s",
794*d57664e9SAndroid Build Coastguard Worker mDirs.valueAt(j)->getPrintableSource().c_str());
795*d57664e9SAndroid Build Coastguard Worker return UNKNOWN_ERROR;
796*d57664e9SAndroid Build Coastguard Worker }
797*d57664e9SAndroid Build Coastguard Worker }
798*d57664e9SAndroid Build Coastguard Worker
799*d57664e9SAndroid Build Coastguard Worker status_t err = mDirs.valueAt(i)->validate();
800*d57664e9SAndroid Build Coastguard Worker if (err != NO_ERROR) {
801*d57664e9SAndroid Build Coastguard Worker return err;
802*d57664e9SAndroid Build Coastguard Worker }
803*d57664e9SAndroid Build Coastguard Worker }
804*d57664e9SAndroid Build Coastguard Worker
805*d57664e9SAndroid Build Coastguard Worker return NO_ERROR;
806*d57664e9SAndroid Build Coastguard Worker }
807*d57664e9SAndroid Build Coastguard Worker
print(const String8 & prefix) const808*d57664e9SAndroid Build Coastguard Worker void AaptDir::print(const String8& prefix) const
809*d57664e9SAndroid Build Coastguard Worker {
810*d57664e9SAndroid Build Coastguard Worker const size_t ND=getDirs().size();
811*d57664e9SAndroid Build Coastguard Worker size_t i;
812*d57664e9SAndroid Build Coastguard Worker for (i=0; i<ND; i++) {
813*d57664e9SAndroid Build Coastguard Worker getDirs().valueAt(i)->print(prefix);
814*d57664e9SAndroid Build Coastguard Worker }
815*d57664e9SAndroid Build Coastguard Worker
816*d57664e9SAndroid Build Coastguard Worker const size_t NF=getFiles().size();
817*d57664e9SAndroid Build Coastguard Worker for (i=0; i<NF; i++) {
818*d57664e9SAndroid Build Coastguard Worker getFiles().valueAt(i)->print(prefix);
819*d57664e9SAndroid Build Coastguard Worker }
820*d57664e9SAndroid Build Coastguard Worker }
821*d57664e9SAndroid Build Coastguard Worker
getPrintableSource() const822*d57664e9SAndroid Build Coastguard Worker String8 AaptDir::getPrintableSource() const
823*d57664e9SAndroid Build Coastguard Worker {
824*d57664e9SAndroid Build Coastguard Worker if (mFiles.size() > 0) {
825*d57664e9SAndroid Build Coastguard Worker // Arbitrarily pull the first file out of the list as the source dir.
826*d57664e9SAndroid Build Coastguard Worker return getPathDir(mFiles.valueAt(0)->getPrintableSource());
827*d57664e9SAndroid Build Coastguard Worker }
828*d57664e9SAndroid Build Coastguard Worker if (mDirs.size() > 0) {
829*d57664e9SAndroid Build Coastguard Worker // Or arbitrarily pull the first dir out of the list as the source dir.
830*d57664e9SAndroid Build Coastguard Worker return getPathDir(mDirs.valueAt(0)->getPrintableSource());
831*d57664e9SAndroid Build Coastguard Worker }
832*d57664e9SAndroid Build Coastguard Worker
833*d57664e9SAndroid Build Coastguard Worker // Should never hit this case, but to be safe...
834*d57664e9SAndroid Build Coastguard Worker return mPath;
835*d57664e9SAndroid Build Coastguard Worker
836*d57664e9SAndroid Build Coastguard Worker }
837*d57664e9SAndroid Build Coastguard Worker
838*d57664e9SAndroid Build Coastguard Worker // =========================================================================
839*d57664e9SAndroid Build Coastguard Worker // =========================================================================
840*d57664e9SAndroid Build Coastguard Worker // =========================================================================
841*d57664e9SAndroid Build Coastguard Worker
applyJavaSymbols(const sp<AaptSymbols> & javaSymbols)842*d57664e9SAndroid Build Coastguard Worker status_t AaptSymbols::applyJavaSymbols(const sp<AaptSymbols>& javaSymbols)
843*d57664e9SAndroid Build Coastguard Worker {
844*d57664e9SAndroid Build Coastguard Worker status_t err = NO_ERROR;
845*d57664e9SAndroid Build Coastguard Worker size_t N = javaSymbols->mSymbols.size();
846*d57664e9SAndroid Build Coastguard Worker for (size_t i=0; i<N; i++) {
847*d57664e9SAndroid Build Coastguard Worker const String8& name = javaSymbols->mSymbols.keyAt(i);
848*d57664e9SAndroid Build Coastguard Worker const AaptSymbolEntry& entry = javaSymbols->mSymbols.valueAt(i);
849*d57664e9SAndroid Build Coastguard Worker ssize_t pos = mSymbols.indexOfKey(name);
850*d57664e9SAndroid Build Coastguard Worker if (pos < 0) {
851*d57664e9SAndroid Build Coastguard Worker entry.sourcePos.error("Symbol '%s' declared with <java-symbol> not defined\n", name.c_str());
852*d57664e9SAndroid Build Coastguard Worker err = UNKNOWN_ERROR;
853*d57664e9SAndroid Build Coastguard Worker continue;
854*d57664e9SAndroid Build Coastguard Worker }
855*d57664e9SAndroid Build Coastguard Worker //printf("**** setting symbol #%d/%d %s to isJavaSymbol=%d\n",
856*d57664e9SAndroid Build Coastguard Worker // i, N, name.c_str(), entry.isJavaSymbol ? 1 : 0);
857*d57664e9SAndroid Build Coastguard Worker mSymbols.editValueAt(pos).isJavaSymbol = entry.isJavaSymbol;
858*d57664e9SAndroid Build Coastguard Worker }
859*d57664e9SAndroid Build Coastguard Worker
860*d57664e9SAndroid Build Coastguard Worker N = javaSymbols->mNestedSymbols.size();
861*d57664e9SAndroid Build Coastguard Worker for (size_t i=0; i<N; i++) {
862*d57664e9SAndroid Build Coastguard Worker const String8& name = javaSymbols->mNestedSymbols.keyAt(i);
863*d57664e9SAndroid Build Coastguard Worker const sp<AaptSymbols>& symbols = javaSymbols->mNestedSymbols.valueAt(i);
864*d57664e9SAndroid Build Coastguard Worker ssize_t pos = mNestedSymbols.indexOfKey(name);
865*d57664e9SAndroid Build Coastguard Worker if (pos < 0) {
866*d57664e9SAndroid Build Coastguard Worker SourcePos pos;
867*d57664e9SAndroid Build Coastguard Worker pos.error("Java symbol dir %s not defined\n", name.c_str());
868*d57664e9SAndroid Build Coastguard Worker err = UNKNOWN_ERROR;
869*d57664e9SAndroid Build Coastguard Worker continue;
870*d57664e9SAndroid Build Coastguard Worker }
871*d57664e9SAndroid Build Coastguard Worker //printf("**** applying java symbols in dir %s\n", name.c_str());
872*d57664e9SAndroid Build Coastguard Worker status_t myerr = mNestedSymbols.valueAt(pos)->applyJavaSymbols(symbols);
873*d57664e9SAndroid Build Coastguard Worker if (myerr != NO_ERROR) {
874*d57664e9SAndroid Build Coastguard Worker err = myerr;
875*d57664e9SAndroid Build Coastguard Worker }
876*d57664e9SAndroid Build Coastguard Worker }
877*d57664e9SAndroid Build Coastguard Worker
878*d57664e9SAndroid Build Coastguard Worker return err;
879*d57664e9SAndroid Build Coastguard Worker }
880*d57664e9SAndroid Build Coastguard Worker
881*d57664e9SAndroid Build Coastguard Worker // =========================================================================
882*d57664e9SAndroid Build Coastguard Worker // =========================================================================
883*d57664e9SAndroid Build Coastguard Worker // =========================================================================
884*d57664e9SAndroid Build Coastguard Worker
AaptAssets()885*d57664e9SAndroid Build Coastguard Worker AaptAssets::AaptAssets()
886*d57664e9SAndroid Build Coastguard Worker : AaptDir(String8(), String8()),
887*d57664e9SAndroid Build Coastguard Worker mHavePrivateSymbols(false),
888*d57664e9SAndroid Build Coastguard Worker mChanged(false), mHaveIncludedAssets(false),
889*d57664e9SAndroid Build Coastguard Worker mRes(NULL) {}
890*d57664e9SAndroid Build Coastguard Worker
getGroupEntries() const891*d57664e9SAndroid Build Coastguard Worker const SortedVector<AaptGroupEntry>& AaptAssets::getGroupEntries() const {
892*d57664e9SAndroid Build Coastguard Worker if (mChanged) {
893*d57664e9SAndroid Build Coastguard Worker }
894*d57664e9SAndroid Build Coastguard Worker return mGroupEntries;
895*d57664e9SAndroid Build Coastguard Worker }
896*d57664e9SAndroid Build Coastguard Worker
addFile(const String8 & name,const sp<AaptGroup> & file)897*d57664e9SAndroid Build Coastguard Worker status_t AaptAssets::addFile(const String8& name, const sp<AaptGroup>& file)
898*d57664e9SAndroid Build Coastguard Worker {
899*d57664e9SAndroid Build Coastguard Worker mChanged = true;
900*d57664e9SAndroid Build Coastguard Worker return AaptDir::addFile(name, file);
901*d57664e9SAndroid Build Coastguard Worker }
902*d57664e9SAndroid Build Coastguard Worker
addFile(const String8 & filePath,const AaptGroupEntry & entry,const String8 & srcDir,sp<AaptGroup> * outGroup,const String8 & resType)903*d57664e9SAndroid Build Coastguard Worker sp<AaptFile> AaptAssets::addFile(
904*d57664e9SAndroid Build Coastguard Worker const String8& filePath, const AaptGroupEntry& entry,
905*d57664e9SAndroid Build Coastguard Worker const String8& srcDir, sp<AaptGroup>* outGroup,
906*d57664e9SAndroid Build Coastguard Worker const String8& resType)
907*d57664e9SAndroid Build Coastguard Worker {
908*d57664e9SAndroid Build Coastguard Worker sp<AaptDir> dir = this;
909*d57664e9SAndroid Build Coastguard Worker sp<AaptGroup> group;
910*d57664e9SAndroid Build Coastguard Worker sp<AaptFile> file;
911*d57664e9SAndroid Build Coastguard Worker String8 root, remain(filePath), partialPath;
912*d57664e9SAndroid Build Coastguard Worker while (remain.length() > 0) {
913*d57664e9SAndroid Build Coastguard Worker root = walkPath(remain, &remain);
914*d57664e9SAndroid Build Coastguard Worker appendPath(partialPath, root);
915*d57664e9SAndroid Build Coastguard Worker
916*d57664e9SAndroid Build Coastguard Worker const String8 rootStr(root);
917*d57664e9SAndroid Build Coastguard Worker
918*d57664e9SAndroid Build Coastguard Worker if (remain.length() == 0) {
919*d57664e9SAndroid Build Coastguard Worker ssize_t i = dir->getFiles().indexOfKey(rootStr);
920*d57664e9SAndroid Build Coastguard Worker if (i >= 0) {
921*d57664e9SAndroid Build Coastguard Worker group = dir->getFiles().valueAt(i);
922*d57664e9SAndroid Build Coastguard Worker } else {
923*d57664e9SAndroid Build Coastguard Worker group = new AaptGroup(rootStr, filePath);
924*d57664e9SAndroid Build Coastguard Worker status_t res = dir->addFile(rootStr, group);
925*d57664e9SAndroid Build Coastguard Worker if (res != NO_ERROR) {
926*d57664e9SAndroid Build Coastguard Worker return NULL;
927*d57664e9SAndroid Build Coastguard Worker }
928*d57664e9SAndroid Build Coastguard Worker }
929*d57664e9SAndroid Build Coastguard Worker file = new AaptFile(appendPathCopy(srcDir, filePath), entry, resType);
930*d57664e9SAndroid Build Coastguard Worker status_t res = group->addFile(file);
931*d57664e9SAndroid Build Coastguard Worker if (res != NO_ERROR) {
932*d57664e9SAndroid Build Coastguard Worker return NULL;
933*d57664e9SAndroid Build Coastguard Worker }
934*d57664e9SAndroid Build Coastguard Worker break;
935*d57664e9SAndroid Build Coastguard Worker
936*d57664e9SAndroid Build Coastguard Worker } else {
937*d57664e9SAndroid Build Coastguard Worker ssize_t i = dir->getDirs().indexOfKey(rootStr);
938*d57664e9SAndroid Build Coastguard Worker if (i >= 0) {
939*d57664e9SAndroid Build Coastguard Worker dir = dir->getDirs().valueAt(i);
940*d57664e9SAndroid Build Coastguard Worker } else {
941*d57664e9SAndroid Build Coastguard Worker sp<AaptDir> subdir = new AaptDir(rootStr, partialPath);
942*d57664e9SAndroid Build Coastguard Worker status_t res = dir->addDir(rootStr, subdir);
943*d57664e9SAndroid Build Coastguard Worker if (res != NO_ERROR) {
944*d57664e9SAndroid Build Coastguard Worker return NULL;
945*d57664e9SAndroid Build Coastguard Worker }
946*d57664e9SAndroid Build Coastguard Worker dir = subdir;
947*d57664e9SAndroid Build Coastguard Worker }
948*d57664e9SAndroid Build Coastguard Worker }
949*d57664e9SAndroid Build Coastguard Worker }
950*d57664e9SAndroid Build Coastguard Worker
951*d57664e9SAndroid Build Coastguard Worker mGroupEntries.add(entry);
952*d57664e9SAndroid Build Coastguard Worker if (outGroup) *outGroup = group;
953*d57664e9SAndroid Build Coastguard Worker return file;
954*d57664e9SAndroid Build Coastguard Worker }
955*d57664e9SAndroid Build Coastguard Worker
addResource(const String8 & leafName,const String8 & path,const sp<AaptFile> & file,const String8 & resType)956*d57664e9SAndroid Build Coastguard Worker void AaptAssets::addResource(const String8& leafName, const String8& path,
957*d57664e9SAndroid Build Coastguard Worker const sp<AaptFile>& file, const String8& resType)
958*d57664e9SAndroid Build Coastguard Worker {
959*d57664e9SAndroid Build Coastguard Worker sp<AaptDir> res = AaptDir::makeDir(kResString);
960*d57664e9SAndroid Build Coastguard Worker String8 dirname = file->getGroupEntry().toDirName(resType);
961*d57664e9SAndroid Build Coastguard Worker sp<AaptDir> subdir = res->makeDir(dirname);
962*d57664e9SAndroid Build Coastguard Worker sp<AaptGroup> grr = new AaptGroup(leafName, path);
963*d57664e9SAndroid Build Coastguard Worker grr->addFile(file);
964*d57664e9SAndroid Build Coastguard Worker
965*d57664e9SAndroid Build Coastguard Worker subdir->addFile(leafName, grr);
966*d57664e9SAndroid Build Coastguard Worker }
967*d57664e9SAndroid Build Coastguard Worker
968*d57664e9SAndroid Build Coastguard Worker
slurpFromArgs(Bundle * bundle)969*d57664e9SAndroid Build Coastguard Worker ssize_t AaptAssets::slurpFromArgs(Bundle* bundle)
970*d57664e9SAndroid Build Coastguard Worker {
971*d57664e9SAndroid Build Coastguard Worker int count;
972*d57664e9SAndroid Build Coastguard Worker int totalCount = 0;
973*d57664e9SAndroid Build Coastguard Worker FileType type;
974*d57664e9SAndroid Build Coastguard Worker const Vector<const char *>& resDirs = bundle->getResourceSourceDirs();
975*d57664e9SAndroid Build Coastguard Worker const size_t dirCount =resDirs.size();
976*d57664e9SAndroid Build Coastguard Worker sp<AaptAssets> current = this;
977*d57664e9SAndroid Build Coastguard Worker
978*d57664e9SAndroid Build Coastguard Worker const int N = bundle->getFileSpecCount();
979*d57664e9SAndroid Build Coastguard Worker
980*d57664e9SAndroid Build Coastguard Worker /*
981*d57664e9SAndroid Build Coastguard Worker * If a package manifest was specified, include that first.
982*d57664e9SAndroid Build Coastguard Worker */
983*d57664e9SAndroid Build Coastguard Worker if (bundle->getAndroidManifestFile() != NULL) {
984*d57664e9SAndroid Build Coastguard Worker // place at root of zip.
985*d57664e9SAndroid Build Coastguard Worker String8 srcFile(bundle->getAndroidManifestFile());
986*d57664e9SAndroid Build Coastguard Worker addFile(getPathLeaf(srcFile), AaptGroupEntry(), getPathDir(srcFile),
987*d57664e9SAndroid Build Coastguard Worker NULL, String8());
988*d57664e9SAndroid Build Coastguard Worker totalCount++;
989*d57664e9SAndroid Build Coastguard Worker }
990*d57664e9SAndroid Build Coastguard Worker
991*d57664e9SAndroid Build Coastguard Worker /*
992*d57664e9SAndroid Build Coastguard Worker * If a directory of custom assets was supplied, slurp 'em up.
993*d57664e9SAndroid Build Coastguard Worker */
994*d57664e9SAndroid Build Coastguard Worker const Vector<const char*>& assetDirs = bundle->getAssetSourceDirs();
995*d57664e9SAndroid Build Coastguard Worker const int AN = assetDirs.size();
996*d57664e9SAndroid Build Coastguard Worker for (int i = 0; i < AN; i++) {
997*d57664e9SAndroid Build Coastguard Worker FileType type = getFileType(assetDirs[i]);
998*d57664e9SAndroid Build Coastguard Worker if (type == kFileTypeNonexistent) {
999*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "ERROR: asset directory '%s' does not exist\n", assetDirs[i]);
1000*d57664e9SAndroid Build Coastguard Worker return UNKNOWN_ERROR;
1001*d57664e9SAndroid Build Coastguard Worker }
1002*d57664e9SAndroid Build Coastguard Worker if (type != kFileTypeDirectory) {
1003*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "ERROR: '%s' is not a directory\n", assetDirs[i]);
1004*d57664e9SAndroid Build Coastguard Worker return UNKNOWN_ERROR;
1005*d57664e9SAndroid Build Coastguard Worker }
1006*d57664e9SAndroid Build Coastguard Worker
1007*d57664e9SAndroid Build Coastguard Worker String8 assetRoot(assetDirs[i]);
1008*d57664e9SAndroid Build Coastguard Worker sp<AaptDir> assetAaptDir = makeDir(String8(kAssetDir));
1009*d57664e9SAndroid Build Coastguard Worker AaptGroupEntry group;
1010*d57664e9SAndroid Build Coastguard Worker count = assetAaptDir->slurpFullTree(bundle, assetRoot, group,
1011*d57664e9SAndroid Build Coastguard Worker String8(), mFullAssetPaths, true);
1012*d57664e9SAndroid Build Coastguard Worker if (count < 0) {
1013*d57664e9SAndroid Build Coastguard Worker totalCount = count;
1014*d57664e9SAndroid Build Coastguard Worker goto bail;
1015*d57664e9SAndroid Build Coastguard Worker }
1016*d57664e9SAndroid Build Coastguard Worker if (count > 0) {
1017*d57664e9SAndroid Build Coastguard Worker mGroupEntries.add(group);
1018*d57664e9SAndroid Build Coastguard Worker }
1019*d57664e9SAndroid Build Coastguard Worker totalCount += count;
1020*d57664e9SAndroid Build Coastguard Worker
1021*d57664e9SAndroid Build Coastguard Worker if (bundle->getVerbose()) {
1022*d57664e9SAndroid Build Coastguard Worker printf("Found %d custom asset file%s in %s\n",
1023*d57664e9SAndroid Build Coastguard Worker count, (count==1) ? "" : "s", assetDirs[i]);
1024*d57664e9SAndroid Build Coastguard Worker }
1025*d57664e9SAndroid Build Coastguard Worker }
1026*d57664e9SAndroid Build Coastguard Worker
1027*d57664e9SAndroid Build Coastguard Worker /*
1028*d57664e9SAndroid Build Coastguard Worker * If a directory of resource-specific assets was supplied, slurp 'em up.
1029*d57664e9SAndroid Build Coastguard Worker */
1030*d57664e9SAndroid Build Coastguard Worker for (size_t i=0; i<dirCount; i++) {
1031*d57664e9SAndroid Build Coastguard Worker const char *res = resDirs[i];
1032*d57664e9SAndroid Build Coastguard Worker if (res) {
1033*d57664e9SAndroid Build Coastguard Worker type = getFileType(res);
1034*d57664e9SAndroid Build Coastguard Worker if (type == kFileTypeNonexistent) {
1035*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "ERROR: resource directory '%s' does not exist\n", res);
1036*d57664e9SAndroid Build Coastguard Worker return UNKNOWN_ERROR;
1037*d57664e9SAndroid Build Coastguard Worker }
1038*d57664e9SAndroid Build Coastguard Worker if (type == kFileTypeDirectory) {
1039*d57664e9SAndroid Build Coastguard Worker if (i>0) {
1040*d57664e9SAndroid Build Coastguard Worker sp<AaptAssets> nextOverlay = new AaptAssets();
1041*d57664e9SAndroid Build Coastguard Worker current->setOverlay(nextOverlay);
1042*d57664e9SAndroid Build Coastguard Worker current = nextOverlay;
1043*d57664e9SAndroid Build Coastguard Worker current->setFullResPaths(mFullResPaths);
1044*d57664e9SAndroid Build Coastguard Worker }
1045*d57664e9SAndroid Build Coastguard Worker count = current->slurpResourceTree(bundle, String8(res));
1046*d57664e9SAndroid Build Coastguard Worker if (i > 0 && count > 0) {
1047*d57664e9SAndroid Build Coastguard Worker count = current->filter(bundle);
1048*d57664e9SAndroid Build Coastguard Worker }
1049*d57664e9SAndroid Build Coastguard Worker
1050*d57664e9SAndroid Build Coastguard Worker if (count < 0) {
1051*d57664e9SAndroid Build Coastguard Worker totalCount = count;
1052*d57664e9SAndroid Build Coastguard Worker goto bail;
1053*d57664e9SAndroid Build Coastguard Worker }
1054*d57664e9SAndroid Build Coastguard Worker totalCount += count;
1055*d57664e9SAndroid Build Coastguard Worker }
1056*d57664e9SAndroid Build Coastguard Worker else {
1057*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "ERROR: '%s' is not a directory\n", res);
1058*d57664e9SAndroid Build Coastguard Worker return UNKNOWN_ERROR;
1059*d57664e9SAndroid Build Coastguard Worker }
1060*d57664e9SAndroid Build Coastguard Worker }
1061*d57664e9SAndroid Build Coastguard Worker
1062*d57664e9SAndroid Build Coastguard Worker }
1063*d57664e9SAndroid Build Coastguard Worker /*
1064*d57664e9SAndroid Build Coastguard Worker * Now do any additional raw files.
1065*d57664e9SAndroid Build Coastguard Worker */
1066*d57664e9SAndroid Build Coastguard Worker for (int arg=0; arg<N; arg++) {
1067*d57664e9SAndroid Build Coastguard Worker const char* assetDir = bundle->getFileSpecEntry(arg);
1068*d57664e9SAndroid Build Coastguard Worker
1069*d57664e9SAndroid Build Coastguard Worker FileType type = getFileType(assetDir);
1070*d57664e9SAndroid Build Coastguard Worker if (type == kFileTypeNonexistent) {
1071*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "ERROR: input directory '%s' does not exist\n", assetDir);
1072*d57664e9SAndroid Build Coastguard Worker return UNKNOWN_ERROR;
1073*d57664e9SAndroid Build Coastguard Worker }
1074*d57664e9SAndroid Build Coastguard Worker if (type != kFileTypeDirectory) {
1075*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "ERROR: '%s' is not a directory\n", assetDir);
1076*d57664e9SAndroid Build Coastguard Worker return UNKNOWN_ERROR;
1077*d57664e9SAndroid Build Coastguard Worker }
1078*d57664e9SAndroid Build Coastguard Worker
1079*d57664e9SAndroid Build Coastguard Worker String8 assetRoot(assetDir);
1080*d57664e9SAndroid Build Coastguard Worker
1081*d57664e9SAndroid Build Coastguard Worker if (bundle->getVerbose())
1082*d57664e9SAndroid Build Coastguard Worker printf("Processing raw dir '%s'\n", (const char*) assetDir);
1083*d57664e9SAndroid Build Coastguard Worker
1084*d57664e9SAndroid Build Coastguard Worker /*
1085*d57664e9SAndroid Build Coastguard Worker * Do a recursive traversal of subdir tree. We don't make any
1086*d57664e9SAndroid Build Coastguard Worker * guarantees about ordering, so we're okay with an inorder search
1087*d57664e9SAndroid Build Coastguard Worker * using whatever order the OS happens to hand back to us.
1088*d57664e9SAndroid Build Coastguard Worker */
1089*d57664e9SAndroid Build Coastguard Worker count = slurpFullTree(bundle, assetRoot, AaptGroupEntry(), String8(), mFullAssetPaths);
1090*d57664e9SAndroid Build Coastguard Worker if (count < 0) {
1091*d57664e9SAndroid Build Coastguard Worker /* failure; report error and remove archive */
1092*d57664e9SAndroid Build Coastguard Worker totalCount = count;
1093*d57664e9SAndroid Build Coastguard Worker goto bail;
1094*d57664e9SAndroid Build Coastguard Worker }
1095*d57664e9SAndroid Build Coastguard Worker totalCount += count;
1096*d57664e9SAndroid Build Coastguard Worker
1097*d57664e9SAndroid Build Coastguard Worker if (bundle->getVerbose())
1098*d57664e9SAndroid Build Coastguard Worker printf("Found %d asset file%s in %s\n",
1099*d57664e9SAndroid Build Coastguard Worker count, (count==1) ? "" : "s", assetDir);
1100*d57664e9SAndroid Build Coastguard Worker }
1101*d57664e9SAndroid Build Coastguard Worker
1102*d57664e9SAndroid Build Coastguard Worker count = validate();
1103*d57664e9SAndroid Build Coastguard Worker if (count != NO_ERROR) {
1104*d57664e9SAndroid Build Coastguard Worker totalCount = count;
1105*d57664e9SAndroid Build Coastguard Worker goto bail;
1106*d57664e9SAndroid Build Coastguard Worker }
1107*d57664e9SAndroid Build Coastguard Worker
1108*d57664e9SAndroid Build Coastguard Worker count = filter(bundle);
1109*d57664e9SAndroid Build Coastguard Worker if (count != NO_ERROR) {
1110*d57664e9SAndroid Build Coastguard Worker totalCount = count;
1111*d57664e9SAndroid Build Coastguard Worker goto bail;
1112*d57664e9SAndroid Build Coastguard Worker }
1113*d57664e9SAndroid Build Coastguard Worker
1114*d57664e9SAndroid Build Coastguard Worker bail:
1115*d57664e9SAndroid Build Coastguard Worker return totalCount;
1116*d57664e9SAndroid Build Coastguard Worker }
1117*d57664e9SAndroid Build Coastguard Worker
slurpFullTree(Bundle * bundle,const String8 & srcDir,const AaptGroupEntry & kind,const String8 & resType,sp<FilePathStore> & fullResPaths,const bool overwrite)1118*d57664e9SAndroid Build Coastguard Worker ssize_t AaptAssets::slurpFullTree(Bundle* bundle, const String8& srcDir,
1119*d57664e9SAndroid Build Coastguard Worker const AaptGroupEntry& kind,
1120*d57664e9SAndroid Build Coastguard Worker const String8& resType,
1121*d57664e9SAndroid Build Coastguard Worker sp<FilePathStore>& fullResPaths,
1122*d57664e9SAndroid Build Coastguard Worker const bool overwrite)
1123*d57664e9SAndroid Build Coastguard Worker {
1124*d57664e9SAndroid Build Coastguard Worker ssize_t res = AaptDir::slurpFullTree(bundle, srcDir, kind, resType, fullResPaths, overwrite);
1125*d57664e9SAndroid Build Coastguard Worker if (res > 0) {
1126*d57664e9SAndroid Build Coastguard Worker mGroupEntries.add(kind);
1127*d57664e9SAndroid Build Coastguard Worker }
1128*d57664e9SAndroid Build Coastguard Worker
1129*d57664e9SAndroid Build Coastguard Worker return res;
1130*d57664e9SAndroid Build Coastguard Worker }
1131*d57664e9SAndroid Build Coastguard Worker
slurpResourceTree(Bundle * bundle,const String8 & srcDir)1132*d57664e9SAndroid Build Coastguard Worker ssize_t AaptAssets::slurpResourceTree(Bundle* bundle, const String8& srcDir)
1133*d57664e9SAndroid Build Coastguard Worker {
1134*d57664e9SAndroid Build Coastguard Worker ssize_t err = 0;
1135*d57664e9SAndroid Build Coastguard Worker
1136*d57664e9SAndroid Build Coastguard Worker DIR* dir = opendir(srcDir.c_str());
1137*d57664e9SAndroid Build Coastguard Worker if (dir == NULL) {
1138*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "ERROR: opendir(%s): %s\n", srcDir.c_str(), strerror(errno));
1139*d57664e9SAndroid Build Coastguard Worker return UNKNOWN_ERROR;
1140*d57664e9SAndroid Build Coastguard Worker }
1141*d57664e9SAndroid Build Coastguard Worker
1142*d57664e9SAndroid Build Coastguard Worker status_t count = 0;
1143*d57664e9SAndroid Build Coastguard Worker
1144*d57664e9SAndroid Build Coastguard Worker /*
1145*d57664e9SAndroid Build Coastguard Worker * Run through the directory, looking for dirs that match the
1146*d57664e9SAndroid Build Coastguard Worker * expected pattern.
1147*d57664e9SAndroid Build Coastguard Worker */
1148*d57664e9SAndroid Build Coastguard Worker while (1) {
1149*d57664e9SAndroid Build Coastguard Worker struct dirent* entry = readdir(dir);
1150*d57664e9SAndroid Build Coastguard Worker if (entry == NULL) {
1151*d57664e9SAndroid Build Coastguard Worker break;
1152*d57664e9SAndroid Build Coastguard Worker }
1153*d57664e9SAndroid Build Coastguard Worker
1154*d57664e9SAndroid Build Coastguard Worker if (isHidden(srcDir.c_str(), entry->d_name)) {
1155*d57664e9SAndroid Build Coastguard Worker continue;
1156*d57664e9SAndroid Build Coastguard Worker }
1157*d57664e9SAndroid Build Coastguard Worker
1158*d57664e9SAndroid Build Coastguard Worker String8 subdirName(srcDir);
1159*d57664e9SAndroid Build Coastguard Worker appendPath(subdirName, entry->d_name);
1160*d57664e9SAndroid Build Coastguard Worker
1161*d57664e9SAndroid Build Coastguard Worker AaptGroupEntry group;
1162*d57664e9SAndroid Build Coastguard Worker String8 resType;
1163*d57664e9SAndroid Build Coastguard Worker bool b = group.initFromDirName(entry->d_name, &resType);
1164*d57664e9SAndroid Build Coastguard Worker if (!b) {
1165*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "invalid resource directory name: %s %s\n", srcDir.c_str(),
1166*d57664e9SAndroid Build Coastguard Worker entry->d_name);
1167*d57664e9SAndroid Build Coastguard Worker err = -1;
1168*d57664e9SAndroid Build Coastguard Worker continue;
1169*d57664e9SAndroid Build Coastguard Worker }
1170*d57664e9SAndroid Build Coastguard Worker
1171*d57664e9SAndroid Build Coastguard Worker if (bundle->getMaxResVersion() != NULL && group.getVersionString().length() != 0) {
1172*d57664e9SAndroid Build Coastguard Worker int maxResInt = atoi(bundle->getMaxResVersion());
1173*d57664e9SAndroid Build Coastguard Worker const char *verString = group.getVersionString().c_str();
1174*d57664e9SAndroid Build Coastguard Worker int dirVersionInt = atoi(verString + 1); // skip 'v' in version name
1175*d57664e9SAndroid Build Coastguard Worker if (dirVersionInt > maxResInt) {
1176*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "max res %d, skipping %s\n", maxResInt, entry->d_name);
1177*d57664e9SAndroid Build Coastguard Worker continue;
1178*d57664e9SAndroid Build Coastguard Worker }
1179*d57664e9SAndroid Build Coastguard Worker }
1180*d57664e9SAndroid Build Coastguard Worker
1181*d57664e9SAndroid Build Coastguard Worker FileType type = getFileType(subdirName.c_str());
1182*d57664e9SAndroid Build Coastguard Worker
1183*d57664e9SAndroid Build Coastguard Worker if (type == kFileTypeDirectory) {
1184*d57664e9SAndroid Build Coastguard Worker sp<AaptDir> dir = makeDir(resType);
1185*d57664e9SAndroid Build Coastguard Worker ssize_t res = dir->slurpFullTree(bundle, subdirName, group,
1186*d57664e9SAndroid Build Coastguard Worker resType, mFullResPaths);
1187*d57664e9SAndroid Build Coastguard Worker if (res < 0) {
1188*d57664e9SAndroid Build Coastguard Worker count = res;
1189*d57664e9SAndroid Build Coastguard Worker goto bail;
1190*d57664e9SAndroid Build Coastguard Worker }
1191*d57664e9SAndroid Build Coastguard Worker if (res > 0) {
1192*d57664e9SAndroid Build Coastguard Worker mGroupEntries.add(group);
1193*d57664e9SAndroid Build Coastguard Worker count += res;
1194*d57664e9SAndroid Build Coastguard Worker }
1195*d57664e9SAndroid Build Coastguard Worker
1196*d57664e9SAndroid Build Coastguard Worker // Only add this directory if we don't already have a resource dir
1197*d57664e9SAndroid Build Coastguard Worker // for the current type. This ensures that we only add the dir once
1198*d57664e9SAndroid Build Coastguard Worker // for all configs.
1199*d57664e9SAndroid Build Coastguard Worker sp<AaptDir> rdir = resDir(resType);
1200*d57664e9SAndroid Build Coastguard Worker if (rdir == NULL) {
1201*d57664e9SAndroid Build Coastguard Worker mResDirs.add(dir);
1202*d57664e9SAndroid Build Coastguard Worker }
1203*d57664e9SAndroid Build Coastguard Worker } else {
1204*d57664e9SAndroid Build Coastguard Worker if (bundle->getVerbose()) {
1205*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, " (ignoring file '%s')\n", subdirName.c_str());
1206*d57664e9SAndroid Build Coastguard Worker }
1207*d57664e9SAndroid Build Coastguard Worker }
1208*d57664e9SAndroid Build Coastguard Worker }
1209*d57664e9SAndroid Build Coastguard Worker
1210*d57664e9SAndroid Build Coastguard Worker bail:
1211*d57664e9SAndroid Build Coastguard Worker closedir(dir);
1212*d57664e9SAndroid Build Coastguard Worker dir = NULL;
1213*d57664e9SAndroid Build Coastguard Worker
1214*d57664e9SAndroid Build Coastguard Worker if (err != 0) {
1215*d57664e9SAndroid Build Coastguard Worker return err;
1216*d57664e9SAndroid Build Coastguard Worker }
1217*d57664e9SAndroid Build Coastguard Worker return count;
1218*d57664e9SAndroid Build Coastguard Worker }
1219*d57664e9SAndroid Build Coastguard Worker
1220*d57664e9SAndroid Build Coastguard Worker ssize_t
slurpResourceZip(Bundle *,const char * filename)1221*d57664e9SAndroid Build Coastguard Worker AaptAssets::slurpResourceZip(Bundle* /* bundle */, const char* filename)
1222*d57664e9SAndroid Build Coastguard Worker {
1223*d57664e9SAndroid Build Coastguard Worker int count = 0;
1224*d57664e9SAndroid Build Coastguard Worker SortedVector<AaptGroupEntry> entries;
1225*d57664e9SAndroid Build Coastguard Worker
1226*d57664e9SAndroid Build Coastguard Worker ZipFile* zip = new ZipFile;
1227*d57664e9SAndroid Build Coastguard Worker status_t err = zip->open(filename, ZipFile::kOpenReadOnly);
1228*d57664e9SAndroid Build Coastguard Worker if (err != NO_ERROR) {
1229*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "error opening zip file %s\n", filename);
1230*d57664e9SAndroid Build Coastguard Worker count = err;
1231*d57664e9SAndroid Build Coastguard Worker delete zip;
1232*d57664e9SAndroid Build Coastguard Worker return -1;
1233*d57664e9SAndroid Build Coastguard Worker }
1234*d57664e9SAndroid Build Coastguard Worker
1235*d57664e9SAndroid Build Coastguard Worker const int N = zip->getNumEntries();
1236*d57664e9SAndroid Build Coastguard Worker for (int i=0; i<N; i++) {
1237*d57664e9SAndroid Build Coastguard Worker ZipEntry* entry = zip->getEntryByIndex(i);
1238*d57664e9SAndroid Build Coastguard Worker if (entry->getDeleted()) {
1239*d57664e9SAndroid Build Coastguard Worker continue;
1240*d57664e9SAndroid Build Coastguard Worker }
1241*d57664e9SAndroid Build Coastguard Worker
1242*d57664e9SAndroid Build Coastguard Worker String8 entryName(entry->getFileName());
1243*d57664e9SAndroid Build Coastguard Worker
1244*d57664e9SAndroid Build Coastguard Worker String8 dirName = getPathDir(entryName);
1245*d57664e9SAndroid Build Coastguard Worker sp<AaptDir> dir = dirName == "" ? this : makeDir(dirName);
1246*d57664e9SAndroid Build Coastguard Worker
1247*d57664e9SAndroid Build Coastguard Worker String8 resType;
1248*d57664e9SAndroid Build Coastguard Worker AaptGroupEntry kind;
1249*d57664e9SAndroid Build Coastguard Worker
1250*d57664e9SAndroid Build Coastguard Worker String8 remain;
1251*d57664e9SAndroid Build Coastguard Worker if (walkPath(entryName, &remain) == kResourceDir) {
1252*d57664e9SAndroid Build Coastguard Worker // these are the resources, pull their type out of the directory name
1253*d57664e9SAndroid Build Coastguard Worker kind.initFromDirName(walkPath(remain).c_str(), &resType);
1254*d57664e9SAndroid Build Coastguard Worker } else {
1255*d57664e9SAndroid Build Coastguard Worker // these are untyped and don't have an AaptGroupEntry
1256*d57664e9SAndroid Build Coastguard Worker }
1257*d57664e9SAndroid Build Coastguard Worker if (entries.indexOf(kind) < 0) {
1258*d57664e9SAndroid Build Coastguard Worker entries.add(kind);
1259*d57664e9SAndroid Build Coastguard Worker mGroupEntries.add(kind);
1260*d57664e9SAndroid Build Coastguard Worker }
1261*d57664e9SAndroid Build Coastguard Worker
1262*d57664e9SAndroid Build Coastguard Worker // use the one from the zip file if they both exist.
1263*d57664e9SAndroid Build Coastguard Worker dir->removeFile(getPathLeaf(entryName));
1264*d57664e9SAndroid Build Coastguard Worker
1265*d57664e9SAndroid Build Coastguard Worker sp<AaptFile> file = new AaptFile(entryName, kind, resType);
1266*d57664e9SAndroid Build Coastguard Worker status_t err = dir->addLeafFile(getPathLeaf(entryName), file);
1267*d57664e9SAndroid Build Coastguard Worker if (err != NO_ERROR) {
1268*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "err=%s entryName=%s\n", strerror(err), entryName.c_str());
1269*d57664e9SAndroid Build Coastguard Worker count = err;
1270*d57664e9SAndroid Build Coastguard Worker goto bail;
1271*d57664e9SAndroid Build Coastguard Worker }
1272*d57664e9SAndroid Build Coastguard Worker file->setCompressionMethod(entry->getCompressionMethod());
1273*d57664e9SAndroid Build Coastguard Worker
1274*d57664e9SAndroid Build Coastguard Worker #if 0
1275*d57664e9SAndroid Build Coastguard Worker if (entryName == "AndroidManifest.xml") {
1276*d57664e9SAndroid Build Coastguard Worker printf("AndroidManifest.xml\n");
1277*d57664e9SAndroid Build Coastguard Worker }
1278*d57664e9SAndroid Build Coastguard Worker printf("\n\nfile: %s\n", entryName.c_str());
1279*d57664e9SAndroid Build Coastguard Worker #endif
1280*d57664e9SAndroid Build Coastguard Worker
1281*d57664e9SAndroid Build Coastguard Worker size_t len = entry->getUncompressedLen();
1282*d57664e9SAndroid Build Coastguard Worker void* data = zip->uncompress(entry);
1283*d57664e9SAndroid Build Coastguard Worker void* buf = file->editData(len);
1284*d57664e9SAndroid Build Coastguard Worker memcpy(buf, data, len);
1285*d57664e9SAndroid Build Coastguard Worker
1286*d57664e9SAndroid Build Coastguard Worker #if 0
1287*d57664e9SAndroid Build Coastguard Worker const int OFF = 0;
1288*d57664e9SAndroid Build Coastguard Worker const unsigned char* p = (unsigned char*)data;
1289*d57664e9SAndroid Build Coastguard Worker const unsigned char* end = p+len;
1290*d57664e9SAndroid Build Coastguard Worker p += OFF;
1291*d57664e9SAndroid Build Coastguard Worker for (int i=0; i<32 && p < end; i++) {
1292*d57664e9SAndroid Build Coastguard Worker printf("0x%03x ", i*0x10 + OFF);
1293*d57664e9SAndroid Build Coastguard Worker for (int j=0; j<0x10 && p < end; j++) {
1294*d57664e9SAndroid Build Coastguard Worker printf(" %02x", *p);
1295*d57664e9SAndroid Build Coastguard Worker p++;
1296*d57664e9SAndroid Build Coastguard Worker }
1297*d57664e9SAndroid Build Coastguard Worker printf("\n");
1298*d57664e9SAndroid Build Coastguard Worker }
1299*d57664e9SAndroid Build Coastguard Worker #endif
1300*d57664e9SAndroid Build Coastguard Worker
1301*d57664e9SAndroid Build Coastguard Worker free(data);
1302*d57664e9SAndroid Build Coastguard Worker
1303*d57664e9SAndroid Build Coastguard Worker count++;
1304*d57664e9SAndroid Build Coastguard Worker }
1305*d57664e9SAndroid Build Coastguard Worker
1306*d57664e9SAndroid Build Coastguard Worker bail:
1307*d57664e9SAndroid Build Coastguard Worker delete zip;
1308*d57664e9SAndroid Build Coastguard Worker return count;
1309*d57664e9SAndroid Build Coastguard Worker }
1310*d57664e9SAndroid Build Coastguard Worker
filter(Bundle * bundle)1311*d57664e9SAndroid Build Coastguard Worker status_t AaptAssets::filter(Bundle* bundle)
1312*d57664e9SAndroid Build Coastguard Worker {
1313*d57664e9SAndroid Build Coastguard Worker sp<WeakResourceFilter> reqFilter(new WeakResourceFilter());
1314*d57664e9SAndroid Build Coastguard Worker status_t err = reqFilter->parse(bundle->getConfigurations());
1315*d57664e9SAndroid Build Coastguard Worker if (err != NO_ERROR) {
1316*d57664e9SAndroid Build Coastguard Worker return err;
1317*d57664e9SAndroid Build Coastguard Worker }
1318*d57664e9SAndroid Build Coastguard Worker
1319*d57664e9SAndroid Build Coastguard Worker uint32_t preferredDensity = 0;
1320*d57664e9SAndroid Build Coastguard Worker if (bundle->getPreferredDensity().size() > 0) {
1321*d57664e9SAndroid Build Coastguard Worker ResTable_config preferredConfig;
1322*d57664e9SAndroid Build Coastguard Worker if (!AaptConfig::parseDensity(bundle->getPreferredDensity().c_str(), &preferredConfig)) {
1323*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "Error parsing preferred density: %s\n",
1324*d57664e9SAndroid Build Coastguard Worker bundle->getPreferredDensity().c_str());
1325*d57664e9SAndroid Build Coastguard Worker return UNKNOWN_ERROR;
1326*d57664e9SAndroid Build Coastguard Worker }
1327*d57664e9SAndroid Build Coastguard Worker preferredDensity = preferredConfig.density;
1328*d57664e9SAndroid Build Coastguard Worker }
1329*d57664e9SAndroid Build Coastguard Worker
1330*d57664e9SAndroid Build Coastguard Worker if (reqFilter->isEmpty() && preferredDensity == 0) {
1331*d57664e9SAndroid Build Coastguard Worker return NO_ERROR;
1332*d57664e9SAndroid Build Coastguard Worker }
1333*d57664e9SAndroid Build Coastguard Worker
1334*d57664e9SAndroid Build Coastguard Worker if (bundle->getVerbose()) {
1335*d57664e9SAndroid Build Coastguard Worker if (!reqFilter->isEmpty()) {
1336*d57664e9SAndroid Build Coastguard Worker printf("Applying required filter: %s\n",
1337*d57664e9SAndroid Build Coastguard Worker bundle->getConfigurations().c_str());
1338*d57664e9SAndroid Build Coastguard Worker }
1339*d57664e9SAndroid Build Coastguard Worker if (preferredDensity > 0) {
1340*d57664e9SAndroid Build Coastguard Worker printf("Applying preferred density filter: %s\n",
1341*d57664e9SAndroid Build Coastguard Worker bundle->getPreferredDensity().c_str());
1342*d57664e9SAndroid Build Coastguard Worker }
1343*d57664e9SAndroid Build Coastguard Worker }
1344*d57664e9SAndroid Build Coastguard Worker
1345*d57664e9SAndroid Build Coastguard Worker const Vector<sp<AaptDir> >& resdirs = mResDirs;
1346*d57664e9SAndroid Build Coastguard Worker const size_t ND = resdirs.size();
1347*d57664e9SAndroid Build Coastguard Worker for (size_t i=0; i<ND; i++) {
1348*d57664e9SAndroid Build Coastguard Worker const sp<AaptDir>& dir = resdirs.itemAt(i);
1349*d57664e9SAndroid Build Coastguard Worker if (dir->getLeaf() == kValuesDir) {
1350*d57664e9SAndroid Build Coastguard Worker // The "value" dir is special since a single file defines
1351*d57664e9SAndroid Build Coastguard Worker // multiple resources, so we can not do filtering on the
1352*d57664e9SAndroid Build Coastguard Worker // files themselves.
1353*d57664e9SAndroid Build Coastguard Worker continue;
1354*d57664e9SAndroid Build Coastguard Worker }
1355*d57664e9SAndroid Build Coastguard Worker if (dir->getLeaf() == kMipmapDir) {
1356*d57664e9SAndroid Build Coastguard Worker // We also skip the "mipmap" directory, since the point of this
1357*d57664e9SAndroid Build Coastguard Worker // is to include all densities without stripping. If you put
1358*d57664e9SAndroid Build Coastguard Worker // other configurations in here as well they won't be stripped
1359*d57664e9SAndroid Build Coastguard Worker // either... So don't do that. Seriously. What is wrong with you?
1360*d57664e9SAndroid Build Coastguard Worker continue;
1361*d57664e9SAndroid Build Coastguard Worker }
1362*d57664e9SAndroid Build Coastguard Worker
1363*d57664e9SAndroid Build Coastguard Worker const size_t NG = dir->getFiles().size();
1364*d57664e9SAndroid Build Coastguard Worker for (size_t j=0; j<NG; j++) {
1365*d57664e9SAndroid Build Coastguard Worker sp<AaptGroup> grp = dir->getFiles().valueAt(j);
1366*d57664e9SAndroid Build Coastguard Worker
1367*d57664e9SAndroid Build Coastguard Worker // First remove any configurations we know we don't need.
1368*d57664e9SAndroid Build Coastguard Worker for (size_t k=0; k<grp->getFiles().size(); k++) {
1369*d57664e9SAndroid Build Coastguard Worker sp<AaptFile> file = grp->getFiles().valueAt(k);
1370*d57664e9SAndroid Build Coastguard Worker if (k == 0 && grp->getFiles().size() == 1) {
1371*d57664e9SAndroid Build Coastguard Worker // If this is the only file left, we need to keep it.
1372*d57664e9SAndroid Build Coastguard Worker // Otherwise the resource IDs we are using will be inconsistent
1373*d57664e9SAndroid Build Coastguard Worker // with what we get when not stripping. Sucky, but at least
1374*d57664e9SAndroid Build Coastguard Worker // for now we can rely on the back-end doing another filtering
1375*d57664e9SAndroid Build Coastguard Worker // pass to take this out and leave us with this resource name
1376*d57664e9SAndroid Build Coastguard Worker // containing no entries.
1377*d57664e9SAndroid Build Coastguard Worker continue;
1378*d57664e9SAndroid Build Coastguard Worker }
1379*d57664e9SAndroid Build Coastguard Worker if (getPathExtension(file->getPath()) == ".xml") {
1380*d57664e9SAndroid Build Coastguard Worker // We can't remove .xml files at this point, because when
1381*d57664e9SAndroid Build Coastguard Worker // we parse them they may add identifier resources, so
1382*d57664e9SAndroid Build Coastguard Worker // removing them can cause our resource identifiers to
1383*d57664e9SAndroid Build Coastguard Worker // become inconsistent.
1384*d57664e9SAndroid Build Coastguard Worker continue;
1385*d57664e9SAndroid Build Coastguard Worker }
1386*d57664e9SAndroid Build Coastguard Worker const ResTable_config& config(file->getGroupEntry().toParams());
1387*d57664e9SAndroid Build Coastguard Worker if (!reqFilter->match(config)) {
1388*d57664e9SAndroid Build Coastguard Worker if (bundle->getVerbose()) {
1389*d57664e9SAndroid Build Coastguard Worker printf("Pruning unneeded resource: %s\n",
1390*d57664e9SAndroid Build Coastguard Worker file->getPrintableSource().c_str());
1391*d57664e9SAndroid Build Coastguard Worker }
1392*d57664e9SAndroid Build Coastguard Worker grp->removeFile(k);
1393*d57664e9SAndroid Build Coastguard Worker k--;
1394*d57664e9SAndroid Build Coastguard Worker }
1395*d57664e9SAndroid Build Coastguard Worker }
1396*d57664e9SAndroid Build Coastguard Worker
1397*d57664e9SAndroid Build Coastguard Worker // Quick check: no preferred filters, nothing more to do.
1398*d57664e9SAndroid Build Coastguard Worker if (preferredDensity == 0) {
1399*d57664e9SAndroid Build Coastguard Worker continue;
1400*d57664e9SAndroid Build Coastguard Worker }
1401*d57664e9SAndroid Build Coastguard Worker
1402*d57664e9SAndroid Build Coastguard Worker // Get the preferred density if there is one. We do not match exactly for density.
1403*d57664e9SAndroid Build Coastguard Worker // If our preferred density is hdpi but we only have mdpi and xhdpi resources, we
1404*d57664e9SAndroid Build Coastguard Worker // pick xhdpi.
1405*d57664e9SAndroid Build Coastguard Worker for (size_t k=0; k<grp->getFiles().size(); k++) {
1406*d57664e9SAndroid Build Coastguard Worker sp<AaptFile> file = grp->getFiles().valueAt(k);
1407*d57664e9SAndroid Build Coastguard Worker if (k == 0 && grp->getFiles().size() == 1) {
1408*d57664e9SAndroid Build Coastguard Worker // If this is the only file left, we need to keep it.
1409*d57664e9SAndroid Build Coastguard Worker // Otherwise the resource IDs we are using will be inconsistent
1410*d57664e9SAndroid Build Coastguard Worker // with what we get when not stripping. Sucky, but at least
1411*d57664e9SAndroid Build Coastguard Worker // for now we can rely on the back-end doing another filtering
1412*d57664e9SAndroid Build Coastguard Worker // pass to take this out and leave us with this resource name
1413*d57664e9SAndroid Build Coastguard Worker // containing no entries.
1414*d57664e9SAndroid Build Coastguard Worker continue;
1415*d57664e9SAndroid Build Coastguard Worker }
1416*d57664e9SAndroid Build Coastguard Worker if (getPathExtension(file->getPath()) == ".xml") {
1417*d57664e9SAndroid Build Coastguard Worker // We can't remove .xml files at this point, because when
1418*d57664e9SAndroid Build Coastguard Worker // we parse them they may add identifier resources, so
1419*d57664e9SAndroid Build Coastguard Worker // removing them can cause our resource identifiers to
1420*d57664e9SAndroid Build Coastguard Worker // become inconsistent.
1421*d57664e9SAndroid Build Coastguard Worker continue;
1422*d57664e9SAndroid Build Coastguard Worker }
1423*d57664e9SAndroid Build Coastguard Worker const ResTable_config& config(file->getGroupEntry().toParams());
1424*d57664e9SAndroid Build Coastguard Worker if (config.density != 0 && config.density != preferredDensity) {
1425*d57664e9SAndroid Build Coastguard Worker // This is a resource we would prefer not to have. Check
1426*d57664e9SAndroid Build Coastguard Worker // to see if have a similar variation that we would like
1427*d57664e9SAndroid Build Coastguard Worker // to have and, if so, we can drop it.
1428*d57664e9SAndroid Build Coastguard Worker uint32_t bestDensity = config.density;
1429*d57664e9SAndroid Build Coastguard Worker
1430*d57664e9SAndroid Build Coastguard Worker for (size_t m=0; m<grp->getFiles().size(); m++) {
1431*d57664e9SAndroid Build Coastguard Worker if (m == k) {
1432*d57664e9SAndroid Build Coastguard Worker continue;
1433*d57664e9SAndroid Build Coastguard Worker }
1434*d57664e9SAndroid Build Coastguard Worker
1435*d57664e9SAndroid Build Coastguard Worker sp<AaptFile> mfile = grp->getFiles().valueAt(m);
1436*d57664e9SAndroid Build Coastguard Worker const ResTable_config& mconfig(mfile->getGroupEntry().toParams());
1437*d57664e9SAndroid Build Coastguard Worker if (AaptConfig::isSameExcept(config, mconfig, ResTable_config::CONFIG_DENSITY)) {
1438*d57664e9SAndroid Build Coastguard Worker // See if there is a better density resource
1439*d57664e9SAndroid Build Coastguard Worker if (mconfig.density < bestDensity &&
1440*d57664e9SAndroid Build Coastguard Worker mconfig.density >= preferredDensity &&
1441*d57664e9SAndroid Build Coastguard Worker bestDensity > preferredDensity) {
1442*d57664e9SAndroid Build Coastguard Worker // This density is our preferred density, or between our best density and
1443*d57664e9SAndroid Build Coastguard Worker // the preferred density, therefore it is better.
1444*d57664e9SAndroid Build Coastguard Worker bestDensity = mconfig.density;
1445*d57664e9SAndroid Build Coastguard Worker } else if (mconfig.density > bestDensity &&
1446*d57664e9SAndroid Build Coastguard Worker bestDensity < preferredDensity) {
1447*d57664e9SAndroid Build Coastguard Worker // This density is better than our best density and
1448*d57664e9SAndroid Build Coastguard Worker // our best density was smaller than our preferred
1449*d57664e9SAndroid Build Coastguard Worker // density, so it is better.
1450*d57664e9SAndroid Build Coastguard Worker bestDensity = mconfig.density;
1451*d57664e9SAndroid Build Coastguard Worker }
1452*d57664e9SAndroid Build Coastguard Worker }
1453*d57664e9SAndroid Build Coastguard Worker }
1454*d57664e9SAndroid Build Coastguard Worker
1455*d57664e9SAndroid Build Coastguard Worker if (bestDensity != config.density) {
1456*d57664e9SAndroid Build Coastguard Worker if (bundle->getVerbose()) {
1457*d57664e9SAndroid Build Coastguard Worker printf("Pruning unneeded resource: %s\n",
1458*d57664e9SAndroid Build Coastguard Worker file->getPrintableSource().c_str());
1459*d57664e9SAndroid Build Coastguard Worker }
1460*d57664e9SAndroid Build Coastguard Worker grp->removeFile(k);
1461*d57664e9SAndroid Build Coastguard Worker k--;
1462*d57664e9SAndroid Build Coastguard Worker }
1463*d57664e9SAndroid Build Coastguard Worker }
1464*d57664e9SAndroid Build Coastguard Worker }
1465*d57664e9SAndroid Build Coastguard Worker }
1466*d57664e9SAndroid Build Coastguard Worker }
1467*d57664e9SAndroid Build Coastguard Worker
1468*d57664e9SAndroid Build Coastguard Worker return NO_ERROR;
1469*d57664e9SAndroid Build Coastguard Worker }
1470*d57664e9SAndroid Build Coastguard Worker
getSymbolsFor(const String8 & name)1471*d57664e9SAndroid Build Coastguard Worker sp<AaptSymbols> AaptAssets::getSymbolsFor(const String8& name)
1472*d57664e9SAndroid Build Coastguard Worker {
1473*d57664e9SAndroid Build Coastguard Worker sp<AaptSymbols> sym = mSymbols.valueFor(name);
1474*d57664e9SAndroid Build Coastguard Worker if (sym == NULL) {
1475*d57664e9SAndroid Build Coastguard Worker sym = new AaptSymbols();
1476*d57664e9SAndroid Build Coastguard Worker mSymbols.add(name, sym);
1477*d57664e9SAndroid Build Coastguard Worker }
1478*d57664e9SAndroid Build Coastguard Worker return sym;
1479*d57664e9SAndroid Build Coastguard Worker }
1480*d57664e9SAndroid Build Coastguard Worker
getJavaSymbolsFor(const String8 & name)1481*d57664e9SAndroid Build Coastguard Worker sp<AaptSymbols> AaptAssets::getJavaSymbolsFor(const String8& name)
1482*d57664e9SAndroid Build Coastguard Worker {
1483*d57664e9SAndroid Build Coastguard Worker sp<AaptSymbols> sym = mJavaSymbols.valueFor(name);
1484*d57664e9SAndroid Build Coastguard Worker if (sym == NULL) {
1485*d57664e9SAndroid Build Coastguard Worker sym = new AaptSymbols();
1486*d57664e9SAndroid Build Coastguard Worker mJavaSymbols.add(name, sym);
1487*d57664e9SAndroid Build Coastguard Worker }
1488*d57664e9SAndroid Build Coastguard Worker return sym;
1489*d57664e9SAndroid Build Coastguard Worker }
1490*d57664e9SAndroid Build Coastguard Worker
applyJavaSymbols()1491*d57664e9SAndroid Build Coastguard Worker status_t AaptAssets::applyJavaSymbols()
1492*d57664e9SAndroid Build Coastguard Worker {
1493*d57664e9SAndroid Build Coastguard Worker size_t N = mJavaSymbols.size();
1494*d57664e9SAndroid Build Coastguard Worker for (size_t i=0; i<N; i++) {
1495*d57664e9SAndroid Build Coastguard Worker const String8& name = mJavaSymbols.keyAt(i);
1496*d57664e9SAndroid Build Coastguard Worker const sp<AaptSymbols>& symbols = mJavaSymbols.valueAt(i);
1497*d57664e9SAndroid Build Coastguard Worker ssize_t pos = mSymbols.indexOfKey(name);
1498*d57664e9SAndroid Build Coastguard Worker if (pos < 0) {
1499*d57664e9SAndroid Build Coastguard Worker SourcePos pos;
1500*d57664e9SAndroid Build Coastguard Worker pos.error("Java symbol dir %s not defined\n", name.c_str());
1501*d57664e9SAndroid Build Coastguard Worker return UNKNOWN_ERROR;
1502*d57664e9SAndroid Build Coastguard Worker }
1503*d57664e9SAndroid Build Coastguard Worker //printf("**** applying java symbols in dir %s\n", name.c_str());
1504*d57664e9SAndroid Build Coastguard Worker status_t err = mSymbols.valueAt(pos)->applyJavaSymbols(symbols);
1505*d57664e9SAndroid Build Coastguard Worker if (err != NO_ERROR) {
1506*d57664e9SAndroid Build Coastguard Worker return err;
1507*d57664e9SAndroid Build Coastguard Worker }
1508*d57664e9SAndroid Build Coastguard Worker }
1509*d57664e9SAndroid Build Coastguard Worker
1510*d57664e9SAndroid Build Coastguard Worker return NO_ERROR;
1511*d57664e9SAndroid Build Coastguard Worker }
1512*d57664e9SAndroid Build Coastguard Worker
isJavaSymbol(const AaptSymbolEntry & sym,bool includePrivate) const1513*d57664e9SAndroid Build Coastguard Worker bool AaptAssets::isJavaSymbol(const AaptSymbolEntry& sym, bool includePrivate) const {
1514*d57664e9SAndroid Build Coastguard Worker //printf("isJavaSymbol %s: public=%d, includePrivate=%d, isJavaSymbol=%d\n",
1515*d57664e9SAndroid Build Coastguard Worker // sym.name.c_str(), sym.isPublic ? 1 : 0, includePrivate ? 1 : 0,
1516*d57664e9SAndroid Build Coastguard Worker // sym.isJavaSymbol ? 1 : 0);
1517*d57664e9SAndroid Build Coastguard Worker if (!mHavePrivateSymbols) return true;
1518*d57664e9SAndroid Build Coastguard Worker if (sym.isPublic) return true;
1519*d57664e9SAndroid Build Coastguard Worker if (includePrivate && sym.isJavaSymbol) return true;
1520*d57664e9SAndroid Build Coastguard Worker return false;
1521*d57664e9SAndroid Build Coastguard Worker }
1522*d57664e9SAndroid Build Coastguard Worker
buildIncludedResources(Bundle * bundle)1523*d57664e9SAndroid Build Coastguard Worker status_t AaptAssets::buildIncludedResources(Bundle* bundle)
1524*d57664e9SAndroid Build Coastguard Worker {
1525*d57664e9SAndroid Build Coastguard Worker if (mHaveIncludedAssets) {
1526*d57664e9SAndroid Build Coastguard Worker return NO_ERROR;
1527*d57664e9SAndroid Build Coastguard Worker }
1528*d57664e9SAndroid Build Coastguard Worker
1529*d57664e9SAndroid Build Coastguard Worker // Add in all includes.
1530*d57664e9SAndroid Build Coastguard Worker const Vector<String8>& includes = bundle->getPackageIncludes();
1531*d57664e9SAndroid Build Coastguard Worker const size_t packageIncludeCount = includes.size();
1532*d57664e9SAndroid Build Coastguard Worker for (size_t i = 0; i < packageIncludeCount; i++) {
1533*d57664e9SAndroid Build Coastguard Worker if (bundle->getVerbose()) {
1534*d57664e9SAndroid Build Coastguard Worker printf("Including resources from package: %s\n", includes[i].c_str());
1535*d57664e9SAndroid Build Coastguard Worker }
1536*d57664e9SAndroid Build Coastguard Worker
1537*d57664e9SAndroid Build Coastguard Worker if (!mIncludedAssets.addAssetPath(includes[i], NULL)) {
1538*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "ERROR: Asset package include '%s' not found.\n",
1539*d57664e9SAndroid Build Coastguard Worker includes[i].c_str());
1540*d57664e9SAndroid Build Coastguard Worker return UNKNOWN_ERROR;
1541*d57664e9SAndroid Build Coastguard Worker }
1542*d57664e9SAndroid Build Coastguard Worker }
1543*d57664e9SAndroid Build Coastguard Worker
1544*d57664e9SAndroid Build Coastguard Worker const String8& featureOfBase = bundle->getFeatureOfPackage();
1545*d57664e9SAndroid Build Coastguard Worker if (!featureOfBase.empty()) {
1546*d57664e9SAndroid Build Coastguard Worker if (bundle->getVerbose()) {
1547*d57664e9SAndroid Build Coastguard Worker printf("Including base feature resources from package: %s\n",
1548*d57664e9SAndroid Build Coastguard Worker featureOfBase.c_str());
1549*d57664e9SAndroid Build Coastguard Worker }
1550*d57664e9SAndroid Build Coastguard Worker
1551*d57664e9SAndroid Build Coastguard Worker if (!mIncludedAssets.addAssetPath(featureOfBase, NULL)) {
1552*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "ERROR: base feature package '%s' not found.\n",
1553*d57664e9SAndroid Build Coastguard Worker featureOfBase.c_str());
1554*d57664e9SAndroid Build Coastguard Worker return UNKNOWN_ERROR;
1555*d57664e9SAndroid Build Coastguard Worker }
1556*d57664e9SAndroid Build Coastguard Worker }
1557*d57664e9SAndroid Build Coastguard Worker
1558*d57664e9SAndroid Build Coastguard Worker mHaveIncludedAssets = true;
1559*d57664e9SAndroid Build Coastguard Worker
1560*d57664e9SAndroid Build Coastguard Worker return NO_ERROR;
1561*d57664e9SAndroid Build Coastguard Worker }
1562*d57664e9SAndroid Build Coastguard Worker
addIncludedResources(const sp<AaptFile> & file)1563*d57664e9SAndroid Build Coastguard Worker status_t AaptAssets::addIncludedResources(const sp<AaptFile>& file)
1564*d57664e9SAndroid Build Coastguard Worker {
1565*d57664e9SAndroid Build Coastguard Worker const ResTable& res = getIncludedResources();
1566*d57664e9SAndroid Build Coastguard Worker // XXX dirty!
1567*d57664e9SAndroid Build Coastguard Worker return const_cast<ResTable&>(res).add(file->getData(), file->getSize());
1568*d57664e9SAndroid Build Coastguard Worker }
1569*d57664e9SAndroid Build Coastguard Worker
getIncludedResources() const1570*d57664e9SAndroid Build Coastguard Worker const ResTable& AaptAssets::getIncludedResources() const
1571*d57664e9SAndroid Build Coastguard Worker {
1572*d57664e9SAndroid Build Coastguard Worker return mIncludedAssets.getResources(false);
1573*d57664e9SAndroid Build Coastguard Worker }
1574*d57664e9SAndroid Build Coastguard Worker
getAssetManager()1575*d57664e9SAndroid Build Coastguard Worker AssetManager& AaptAssets::getAssetManager()
1576*d57664e9SAndroid Build Coastguard Worker {
1577*d57664e9SAndroid Build Coastguard Worker return mIncludedAssets;
1578*d57664e9SAndroid Build Coastguard Worker }
1579*d57664e9SAndroid Build Coastguard Worker
print(const String8 & prefix) const1580*d57664e9SAndroid Build Coastguard Worker void AaptAssets::print(const String8& prefix) const
1581*d57664e9SAndroid Build Coastguard Worker {
1582*d57664e9SAndroid Build Coastguard Worker String8 innerPrefix(prefix);
1583*d57664e9SAndroid Build Coastguard Worker innerPrefix.append(" ");
1584*d57664e9SAndroid Build Coastguard Worker String8 innerInnerPrefix(innerPrefix);
1585*d57664e9SAndroid Build Coastguard Worker innerInnerPrefix.append(" ");
1586*d57664e9SAndroid Build Coastguard Worker printf("%sConfigurations:\n", prefix.c_str());
1587*d57664e9SAndroid Build Coastguard Worker const size_t N=mGroupEntries.size();
1588*d57664e9SAndroid Build Coastguard Worker for (size_t i=0; i<N; i++) {
1589*d57664e9SAndroid Build Coastguard Worker String8 cname = mGroupEntries.itemAt(i).toDirName(String8());
1590*d57664e9SAndroid Build Coastguard Worker printf("%s %s\n", prefix.c_str(),
1591*d57664e9SAndroid Build Coastguard Worker cname != "" ? cname.c_str() : "(default)");
1592*d57664e9SAndroid Build Coastguard Worker }
1593*d57664e9SAndroid Build Coastguard Worker
1594*d57664e9SAndroid Build Coastguard Worker printf("\n%sFiles:\n", prefix.c_str());
1595*d57664e9SAndroid Build Coastguard Worker AaptDir::print(innerPrefix);
1596*d57664e9SAndroid Build Coastguard Worker
1597*d57664e9SAndroid Build Coastguard Worker printf("\n%sResource Dirs:\n", prefix.c_str());
1598*d57664e9SAndroid Build Coastguard Worker const Vector<sp<AaptDir> >& resdirs = mResDirs;
1599*d57664e9SAndroid Build Coastguard Worker const size_t NR = resdirs.size();
1600*d57664e9SAndroid Build Coastguard Worker for (size_t i=0; i<NR; i++) {
1601*d57664e9SAndroid Build Coastguard Worker const sp<AaptDir>& d = resdirs.itemAt(i);
1602*d57664e9SAndroid Build Coastguard Worker printf("%s Type %s\n", prefix.c_str(), d->getLeaf().c_str());
1603*d57664e9SAndroid Build Coastguard Worker d->print(innerInnerPrefix);
1604*d57664e9SAndroid Build Coastguard Worker }
1605*d57664e9SAndroid Build Coastguard Worker }
1606*d57664e9SAndroid Build Coastguard Worker
resDir(const String8 & name) const1607*d57664e9SAndroid Build Coastguard Worker sp<AaptDir> AaptAssets::resDir(const String8& name) const
1608*d57664e9SAndroid Build Coastguard Worker {
1609*d57664e9SAndroid Build Coastguard Worker const Vector<sp<AaptDir> >& resdirs = mResDirs;
1610*d57664e9SAndroid Build Coastguard Worker const size_t N = resdirs.size();
1611*d57664e9SAndroid Build Coastguard Worker for (size_t i=0; i<N; i++) {
1612*d57664e9SAndroid Build Coastguard Worker const sp<AaptDir>& d = resdirs.itemAt(i);
1613*d57664e9SAndroid Build Coastguard Worker if (d->getLeaf() == name) {
1614*d57664e9SAndroid Build Coastguard Worker return d;
1615*d57664e9SAndroid Build Coastguard Worker }
1616*d57664e9SAndroid Build Coastguard Worker }
1617*d57664e9SAndroid Build Coastguard Worker return NULL;
1618*d57664e9SAndroid Build Coastguard Worker }
1619*d57664e9SAndroid Build Coastguard Worker
1620*d57664e9SAndroid Build Coastguard Worker bool
valid_symbol_name(const String8 & symbol)1621*d57664e9SAndroid Build Coastguard Worker valid_symbol_name(const String8& symbol)
1622*d57664e9SAndroid Build Coastguard Worker {
1623*d57664e9SAndroid Build Coastguard Worker static char const * const KEYWORDS[] = {
1624*d57664e9SAndroid Build Coastguard Worker "abstract", "assert", "boolean", "break",
1625*d57664e9SAndroid Build Coastguard Worker "byte", "case", "catch", "char", "class", "const", "continue",
1626*d57664e9SAndroid Build Coastguard Worker "default", "do", "double", "else", "enum", "extends", "final",
1627*d57664e9SAndroid Build Coastguard Worker "finally", "float", "for", "goto", "if", "implements", "import",
1628*d57664e9SAndroid Build Coastguard Worker "instanceof", "int", "interface", "long", "native", "new", "package",
1629*d57664e9SAndroid Build Coastguard Worker "private", "protected", "public", "return", "short", "static",
1630*d57664e9SAndroid Build Coastguard Worker "strictfp", "super", "switch", "synchronized", "this", "throw",
1631*d57664e9SAndroid Build Coastguard Worker "throws", "transient", "try", "void", "volatile", "while",
1632*d57664e9SAndroid Build Coastguard Worker "true", "false", "null",
1633*d57664e9SAndroid Build Coastguard Worker NULL
1634*d57664e9SAndroid Build Coastguard Worker };
1635*d57664e9SAndroid Build Coastguard Worker const char*const* k = KEYWORDS;
1636*d57664e9SAndroid Build Coastguard Worker const char*const s = symbol.c_str();
1637*d57664e9SAndroid Build Coastguard Worker while (*k) {
1638*d57664e9SAndroid Build Coastguard Worker if (0 == strcmp(s, *k)) {
1639*d57664e9SAndroid Build Coastguard Worker return false;
1640*d57664e9SAndroid Build Coastguard Worker }
1641*d57664e9SAndroid Build Coastguard Worker k++;
1642*d57664e9SAndroid Build Coastguard Worker }
1643*d57664e9SAndroid Build Coastguard Worker return true;
1644*d57664e9SAndroid Build Coastguard Worker }
1645