AaptAssets.cpp revision 7960898f6f886aadda1dd3d7a89106dde9f44217
1282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//
2282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// Copyright 2006 The Android Open Source Project
3282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//
4282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
5282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "AaptAssets.h"
6fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski#include "AaptConfig.h"
7fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski#include "AaptUtil.h"
8282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "Main.h"
9fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski#include "ResourceFilter.h"
10282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
11282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <utils/misc.h>
12282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <utils/SortedVector.h>
13282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
14282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <ctype.h>
15282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <dirent.h>
16282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <errno.h>
17282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
18282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char* kAssetDir = "assets";
19282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char* kResourceDir = "res";
20282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char* kValuesDir = "values";
21282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char* kMipmapDir = "mipmap";
22282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char* kInvalidChars = "/\\:";
23282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const size_t kMaxAssetFileName = 100;
24282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
25282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const String8 kResString(kResourceDir);
26282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
27282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
28282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Names of asset files must meet the following criteria:
29282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
30282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *  - the filename length must be less than kMaxAssetFileName bytes long
31282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *    (and can't be empty)
32282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *  - all characters must be 7-bit printable ASCII
33282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *  - none of { '/' '\\' ':' }
34282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
35282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Pass in just the filename, not the full path.
36282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
37282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic bool validateFileName(const char* fileName)
38282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
39282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char* cp = fileName;
40282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t len = 0;
41282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
42282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (*cp != '\0') {
43282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if ((*cp & 0x80) != 0)
44282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;           // reject high ASCII
45282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (*cp < 0x20 || *cp >= 0x7f)
46282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;           // reject control chars and 0x7f
47282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (strchr(kInvalidChars, *cp) != NULL)
48282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;           // reject path sep chars
49282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        cp++;
50282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        len++;
51282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
52282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
53282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (len < 1 || len > kMaxAssetFileName)
54282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return false;               // reject empty or too long
55282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
56282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return true;
57282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
58282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
59282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// The default to use if no other ignore pattern is defined.
60282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiconst char * const gDefaultIgnoreAssets =
61282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    "!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~";
62282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// The ignore pattern that can be passed via --ignore-assets in Main.cpp
63282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiconst char * gUserIgnoreAssets = NULL;
64282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
65282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic bool isHidden(const char *root, const char *path)
66282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
67282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Patterns syntax:
68282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // - Delimiter is :
69282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // - Entry can start with the flag ! to avoid printing a warning
70282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //   about the file being ignored.
71282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // - Entry can have the flag "<dir>" to match only directories
72282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //   or <file> to match only files. Default is to match both.
73282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // - Entry can be a simplified glob "<prefix>*" or "*<suffix>"
74282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //   where prefix/suffix must have at least 1 character (so that
75282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //   we don't match a '*' catch-all pattern.)
76282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // - The special filenames "." and ".." are always ignored.
77282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // - Otherwise the full string is matched.
78282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // - match is not case-sensitive.
79282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
80282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (strcmp(path, ".") == 0 || strcmp(path, "..") == 0) {
81282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
82282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
83282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
84282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char *delim = ":";
85282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char *p = gUserIgnoreAssets;
86282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (!p || !p[0]) {
87282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        p = getenv("ANDROID_AAPT_IGNORE");
88282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
89282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (!p || !p[0]) {
90282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        p = gDefaultIgnoreAssets;
91282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
92282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    char *patterns = strdup(p);
93282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
94282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool ignore = false;
95282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool chatty = true;
96282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    char *matchedPattern = NULL;
97282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
98282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String8 fullPath(root);
99282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fullPath.appendPath(path);
100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    FileType type = getFileType(fullPath);
101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int plen = strlen(path);
103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Note: we don't have strtok_r under mingw.
105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for(char *token = strtok(patterns, delim);
106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            !ignore && token != NULL;
107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            token = strtok(NULL, delim)) {
108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        chatty = token[0] != '!';
109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!chatty) token++; // skip !
110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (strncasecmp(token, "<dir>" , 5) == 0) {
111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (type != kFileTypeDirectory) continue;
112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            token += 5;
113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (strncasecmp(token, "<file>", 6) == 0) {
115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (type != kFileTypeRegular) continue;
116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            token += 6;
117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        matchedPattern = token;
120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int n = strlen(token);
121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (token[0] == '*') {
123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Match *suffix
124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            token++;
125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            n--;
126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (n <= plen) {
127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ignore = strncasecmp(token, path + plen - n, n) == 0;
128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else if (n > 1 && token[n - 1] == '*') {
130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Match prefix*
131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ignore = strncasecmp(token, path, n - 1) == 0;
132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ignore = strcasecmp(token, path) == 0;
134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (ignore && chatty) {
138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "    (skipping %s '%s' due to ANDROID_AAPT_IGNORE pattern '%s')\n",
139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                type == kFileTypeDirectory ? "dir" : "file",
140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                path,
141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                matchedPattern ? matchedPattern : "");
142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    free(patterns);
145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return ignore;
146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =========================================================================
149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =========================================================================
150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =========================================================================
151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
15291447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath/* static */
15391447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamathinline bool isAlpha(const String8& string) {
15491447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath     const size_t length = string.length();
15591447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath     for (size_t i = 0; i < length; ++i) {
15691447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath          if (!isalpha(string[i])) {
15791447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath              return false;
15891447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath          }
15991447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath     }
16091447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath
16191447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath     return true;
16291447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath}
16391447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath
16491447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath/* static */
16591447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamathinline bool isNumber(const String8& string) {
16691447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath     const size_t length = string.length();
16791447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath     for (size_t i = 0; i < length; ++i) {
16891447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath          if (!isdigit(string[i])) {
16991447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath              return false;
17091447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath          }
17191447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath     }
17291447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath
17391447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath     return true;
17491447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath}
17591447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath
17691447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamathvoid AaptLocaleValue::setLanguage(const char* languageChars) {
17791447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath     size_t i = 0;
178b8dc7bc582ee4acd9d6c1379701a002c5ddbe323Andreas Gampe     while ((*languageChars) != '\0' && i < sizeof(language)/sizeof(language[0])) {
17991447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath          language[i++] = tolower(*languageChars);
18091447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath          languageChars++;
18191447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath     }
18291447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath}
18391447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath
18491447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamathvoid AaptLocaleValue::setRegion(const char* regionChars) {
18591447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath    size_t i = 0;
186b8dc7bc582ee4acd9d6c1379701a002c5ddbe323Andreas Gampe    while ((*regionChars) != '\0' && i < sizeof(region)/sizeof(region[0])) {
18791447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath         region[i++] = toupper(*regionChars);
18891447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath         regionChars++;
18991447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath    }
19091447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath}
19191447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath
19291447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamathvoid AaptLocaleValue::setScript(const char* scriptChars) {
19391447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath    size_t i = 0;
194b8dc7bc582ee4acd9d6c1379701a002c5ddbe323Andreas Gampe    while ((*scriptChars) != '\0' && i < sizeof(script)/sizeof(script[0])) {
19591447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath         if (i == 0) {
19691447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath             script[i++] = toupper(*scriptChars);
19791447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath         } else {
19891447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath             script[i++] = tolower(*scriptChars);
19991447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath         }
20091447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath         scriptChars++;
20191447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath    }
20291447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath}
20391447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath
20491447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamathvoid AaptLocaleValue::setVariant(const char* variantChars) {
20591447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath     size_t i = 0;
206b8dc7bc582ee4acd9d6c1379701a002c5ddbe323Andreas Gampe     while ((*variantChars) != '\0' && i < sizeof(variant)/sizeof(variant[0])) {
20791447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath          variant[i++] = *variantChars;
20891447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath          variantChars++;
20991447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath     }
21091447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath}
21191447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath
21291447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamathbool AaptLocaleValue::initFromFilterString(const String8& str) {
21391447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath     // A locale (as specified in the filter) is an underscore separated name such
21491447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath     // as "en_US", "en_Latn_US", or "en_US_POSIX".
215fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     Vector<String8> parts = AaptUtil::splitAndLowerCase(str, '_');
21691447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath
21791447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath     const int numTags = parts.size();
21891447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath     bool valid = false;
21991447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath     if (numTags >= 1) {
22091447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath         const String8& lang = parts[0];
22191447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath         if (isAlpha(lang) && (lang.length() == 2 || lang.length() == 3)) {
22291447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath             setLanguage(lang.string());
22391447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath             valid = true;
22491447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath         }
22591447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath     }
22691447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath
22791447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath     if (!valid || numTags == 1) {
228fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski         return valid;
229fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     }
230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
231fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     // At this point, valid == true && numTags > 1.
232fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     const String8& part2 = parts[1];
233fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     if ((part2.length() == 2 && isAlpha(part2)) ||
234fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski         (part2.length() == 3 && isNumber(part2))) {
235fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski         setRegion(part2.string());
236fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     } else if (part2.length() == 4 && isAlpha(part2)) {
237fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski         setScript(part2.string());
238b927c559e1ef8530b08712507f320502627db298Roozbeh Pournader     } else if (part2.length() >= 4 && part2.length() <= 8) {
239fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski         setVariant(part2.string());
240fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     } else {
241fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski         valid = false;
242fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     }
243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
244fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     if (!valid || numTags == 2) {
245fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski         return valid;
246fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     }
247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
248fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     // At this point, valid == true && numTags > 1.
249fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     const String8& part3 = parts[2];
250fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     if (((part3.length() == 2 && isAlpha(part3)) ||
251fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski         (part3.length() == 3 && isNumber(part3))) && script[0]) {
252fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski         setRegion(part3.string());
253b927c559e1ef8530b08712507f320502627db298Roozbeh Pournader     } else if (part3.length() >= 4 && part3.length() <= 8) {
254fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski         setVariant(part3.string());
255fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     } else {
256fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski         valid = false;
257fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     }
258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
259fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     if (!valid || numTags == 3) {
260fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski         return valid;
261fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     }
262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
263fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     const String8& part4 = parts[3];
264b927c559e1ef8530b08712507f320502627db298Roozbeh Pournader     if (part4.length() >= 4 && part4.length() <= 8) {
265fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski         setVariant(part4.string());
266fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     } else {
267fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski         valid = false;
268fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     }
269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
270fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     if (!valid || numTags > 4) {
271fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski         return false;
272fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     }
273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
274fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     return true;
275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
277fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinskiint AaptLocaleValue::initFromDirName(const Vector<String8>& parts, const int startIndex) {
278fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    const int size = parts.size();
279fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    int currentIndex = startIndex;
280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
281fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    String8 part = parts[currentIndex];
282fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (part[0] == 'b' && part[1] == '+') {
283b927c559e1ef8530b08712507f320502627db298Roozbeh Pournader        // This is a "modified" BCP 47 language tag. Same semantics as BCP 47 tags,
284fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        // except that the separator is "+" and not "-".
285fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        Vector<String8> subtags = AaptUtil::splitAndLowerCase(part, '+');
286fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        subtags.removeItemsAt(0);
287fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        if (subtags.size() == 1) {
288fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            setLanguage(subtags[0]);
289fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        } else if (subtags.size() == 2) {
290fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            setLanguage(subtags[0]);
291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
292fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            // The second tag can either be a region, a variant or a script.
293fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            switch (subtags[1].size()) {
294fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                case 2:
295fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                case 3:
296fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    setRegion(subtags[1]);
297fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    break;
298fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                case 4:
299b927c559e1ef8530b08712507f320502627db298Roozbeh Pournader                    if (isAlpha(subtags[1])) {
300b927c559e1ef8530b08712507f320502627db298Roozbeh Pournader                        setScript(subtags[1]);
301b927c559e1ef8530b08712507f320502627db298Roozbeh Pournader                        break;
302b927c559e1ef8530b08712507f320502627db298Roozbeh Pournader                    }
303b927c559e1ef8530b08712507f320502627db298Roozbeh Pournader                    // This is not alphabetical, so we fall through to variant
304fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                case 5:
305fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                case 6:
306fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                case 7:
307fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                case 8:
308fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    setVariant(subtags[1]);
309fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    break;
310fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                default:
311b927c559e1ef8530b08712507f320502627db298Roozbeh Pournader                    fprintf(stderr, "ERROR: Invalid BCP 47 tag in directory name %s\n",
312fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                            part.string());
313fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    return -1;
314fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            }
315fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        } else if (subtags.size() == 3) {
316fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            // The language is always the first subtag.
317fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            setLanguage(subtags[0]);
318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
319fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            // The second subtag can either be a script or a region code.
320fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            // If its size is 4, it's a script code, else it's a region code.
321fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            bool hasRegion = false;
322fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            if (subtags[1].size() == 4) {
323fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                setScript(subtags[1]);
324fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            } else if (subtags[1].size() == 2 || subtags[1].size() == 3) {
325fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                setRegion(subtags[1]);
326fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                hasRegion = true;
327fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            } else {
328b927c559e1ef8530b08712507f320502627db298Roozbeh Pournader                fprintf(stderr, "ERROR: Invalid BCP 47 tag in directory name %s\n", part.string());
329fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                return -1;
330fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            }
331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
332fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            // The third tag can either be a region code (if the second tag was
333fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            // a script), else a variant code.
334b927c559e1ef8530b08712507f320502627db298Roozbeh Pournader            if (subtags[2].size() >= 4) {
335fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                setVariant(subtags[2]);
336fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            } else {
337fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                setRegion(subtags[2]);
338fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            }
339fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        } else if (subtags.size() == 4) {
340fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            setLanguage(subtags[0]);
341fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            setScript(subtags[1]);
342fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            setRegion(subtags[2]);
343fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            setVariant(subtags[3]);
344fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        } else {
345b927c559e1ef8530b08712507f320502627db298Roozbeh Pournader            fprintf(stderr, "ERROR: Invalid BCP 47 tag in directory name: %s\n", part.string());
346fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            return -1;
347fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        }
348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
349fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        return ++currentIndex;
350fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    } else {
3517f1a8957cca420d525719836069b7f6d5ee04718Narayan Kamath        if ((part.length() == 2 || part.length() == 3)
3527f1a8957cca420d525719836069b7f6d5ee04718Narayan Kamath               && isAlpha(part) && strcmp("car", part.string())) {
353fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            setLanguage(part);
354fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            if (++currentIndex == size) {
355fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                return size;
356fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            }
357fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        } else {
358fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            return currentIndex;
359fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        }
360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
361fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        part = parts[currentIndex];
362fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        if (part.string()[0] == 'r' && part.length() == 3) {
363fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            setRegion(part.string() + 1);
364fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            if (++currentIndex == size) {
365fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                return size;
366fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            }
367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
370fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    return currentIndex;
371fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski}
372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
373fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinskivoid AaptLocaleValue::initFromResTable(const ResTable_config& config) {
374fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    config.unpackLanguage(language);
375fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    config.unpackRegion(region);
3767960898f6f886aadda1dd3d7a89106dde9f44217Roozbeh Pournader    if (config.localeScript[0] && !config.localeScriptWasComputed) {
377fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        memcpy(script, config.localeScript, sizeof(config.localeScript));
378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
380fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (config.localeVariant[0]) {
381fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        memcpy(variant, config.localeVariant, sizeof(config.localeVariant));
382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
385fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinskivoid AaptLocaleValue::writeTo(ResTable_config* out) const {
386fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    out->packLanguage(language);
387fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    out->packRegion(region);
388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
389fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (script[0]) {
390fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        memcpy(out->localeScript, script, sizeof(out->localeScript));
3917960898f6f886aadda1dd3d7a89106dde9f44217Roozbeh Pournader        out->localeScriptWasComputed = false;
392b927c559e1ef8530b08712507f320502627db298Roozbeh Pournader    } else {
393b927c559e1ef8530b08712507f320502627db298Roozbeh Pournader        out->computeScript();
3947960898f6f886aadda1dd3d7a89106dde9f44217Roozbeh Pournader        out->localeScriptWasComputed = true;
395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
397fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (variant[0]) {
398fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        memcpy(out->localeVariant, variant, sizeof(out->localeVariant));
399fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    }
400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
402fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinskibool
403fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam LesinskiAaptGroupEntry::initFromDirName(const char* dir, String8* resType)
404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
405fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    const char* q = strchr(dir, '-');
406fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    size_t typeLen;
407fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (q != NULL) {
408fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        typeLen = q - dir;
409fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    } else {
410fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        typeLen = strlen(dir);
411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
413fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    String8 type(dir, typeLen);
414fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (!isValidResourceType(type)) {
415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return false;
416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
418fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (q != NULL) {
419fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        if (!AaptConfig::parse(String8(q + 1), &mParams)) {
420fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            return false;
421fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        }
422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
424fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    *resType = type;
425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return true;
426282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
428fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam LesinskiString8
429fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam LesinskiAaptGroupEntry::toDirName(const String8& resType) const
430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
431fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    String8 s = resType;
432fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    String8 params = mParams.toString();
433fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (params.length() > 0) {
434fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        if (s.length() > 0) {
435fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            s += "-";
436fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        }
437fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        s += params;
438fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    }
439fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    return s;
440282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
441282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =========================================================================
444282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =========================================================================
445282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =========================================================================
446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid* AaptFile::editData(size_t size)
448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (size <= mBufferSize) {
450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mDataSize = size;
451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return mData;
452282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t allocSize = (size*3)/2;
454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    void* buf = realloc(mData, allocSize);
455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (buf == NULL) {
456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NULL;
457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mData = buf;
459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mDataSize = size;
460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mBufferSize = allocSize;
461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return buf;
462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
464de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinskivoid* AaptFile::editDataInRange(size_t offset, size_t size)
465de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski{
466de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski    return (void*)(((uint8_t*) editData(offset + size)) + offset);
467de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski}
468de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski
469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid* AaptFile::editData(size_t* outSize)
470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (outSize) {
472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        *outSize = mDataSize;
473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return mData;
475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid* AaptFile::padData(size_t wordSize)
478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
479282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t extra = mDataSize%wordSize;
480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (extra == 0) {
481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return mData;
482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t initial = mDataSize;
485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    void* data = editData(initial+(wordSize-extra));
486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (data != NULL) {
487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        memset(((uint8_t*)data) + initial, 0, wordSize-extra);
488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return data;
490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t AaptFile::writeData(const void* data, size_t size)
493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t end = mDataSize;
495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t total = size + end;
496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    void* buf = editData(total);
497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (buf == NULL) {
498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    memcpy(((char*)buf)+end, data, size);
501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
504282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid AaptFile::clearData()
505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mData != NULL) free(mData);
507282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mData = NULL;
508282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mDataSize = 0;
509282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mBufferSize = 0;
510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
511282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
512282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiString8 AaptFile::getPrintableSource() const
513282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
514282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (hasData()) {
515282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String8 name(mGroupEntry.toDirName(String8()));
516282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        name.appendPath(mPath);
517282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        name.append(" #generated");
518282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return name;
519282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
520282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return mSourceFile;
521282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
522282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
523282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =========================================================================
524282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =========================================================================
525282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =========================================================================
526282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
52709384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinskistatus_t AaptGroup::addFile(const sp<AaptFile>& file, const bool overwriteDuplicate)
528282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
52909384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski    ssize_t index = mFiles.indexOfKey(file->getGroupEntry());
53009384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski    if (index >= 0 && overwriteDuplicate) {
53109384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski        fprintf(stderr, "warning: overwriting '%s' with '%s'\n",
53209384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski                mFiles[index]->getSourceFile().string(),
53309384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski                file->getSourceFile().string());
53409384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski        removeFile(index);
53509384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski        index = -1;
53609384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski    }
53709384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski
53809384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski    if (index < 0) {
539282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        file->mPath = mPath;
540282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mFiles.add(file->getGroupEntry(), file);
541282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NO_ERROR;
542282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
543282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
54448f05d29f398576c76b2c3b47a22f4e44e8919fcAdam Lesinski    // Check if the version is automatically applied. This is a common source of
54548f05d29f398576c76b2c3b47a22f4e44e8919fcAdam Lesinski    // error.
54648f05d29f398576c76b2c3b47a22f4e44e8919fcAdam Lesinski    ConfigDescription withoutVersion = file->getGroupEntry().toParams();
54748f05d29f398576c76b2c3b47a22f4e44e8919fcAdam Lesinski    withoutVersion.version = 0;
54848f05d29f398576c76b2c3b47a22f4e44e8919fcAdam Lesinski    AaptConfig::applyVersionForCompatibility(&withoutVersion);
54948f05d29f398576c76b2c3b47a22f4e44e8919fcAdam Lesinski
55048f05d29f398576c76b2c3b47a22f4e44e8919fcAdam Lesinski    const sp<AaptFile>& originalFile = mFiles.valueAt(index);
55148f05d29f398576c76b2c3b47a22f4e44e8919fcAdam Lesinski    SourcePos(file->getSourceFile(), -1)
55248f05d29f398576c76b2c3b47a22f4e44e8919fcAdam Lesinski            .error("Duplicate file.\n%s: Original is here. %s",
55348f05d29f398576c76b2c3b47a22f4e44e8919fcAdam Lesinski                   originalFile->getPrintableSource().string(),
55448f05d29f398576c76b2c3b47a22f4e44e8919fcAdam Lesinski                   (withoutVersion.version != 0) ? "The version qualifier may be implied." : "");
555282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return UNKNOWN_ERROR;
556282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
557282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
558282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid AaptGroup::removeFile(size_t index)
559282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
560282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski	mFiles.removeItemsAt(index);
561282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
562282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
563282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid AaptGroup::print(const String8& prefix) const
564282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
565282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    printf("%s%s\n", prefix.string(), getPath().string());
566282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t N=mFiles.size();
567282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t i;
568282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (i=0; i<N; i++) {
569282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<AaptFile> file = mFiles.valueAt(i);
570282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const AaptGroupEntry& e = file->getGroupEntry();
571282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (file->hasData()) {
572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("%s  Gen: (%s) %d bytes\n", prefix.string(), e.toDirName(String8()).string(),
573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    (int)file->getSize());
574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("%s  Src: (%s) %s\n", prefix.string(), e.toDirName(String8()).string(),
576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    file->getPrintableSource().string());
577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //printf("%s  File Group Entry: %s\n", prefix.string(),
579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //        file->getGroupEntry().toDirName(String8()).string());
580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
583282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiString8 AaptGroup::getPrintableSource() const
584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mFiles.size() > 0) {
586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Arbitrarily pull the first source file out of the list.
587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return mFiles.valueAt(0)->getPrintableSource();
588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Should never hit this case, but to be safe...
591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return getPath();
592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
593282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =========================================================================
596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =========================================================================
597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =========================================================================
598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t AaptDir::addFile(const String8& name, const sp<AaptGroup>& file)
600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mFiles.indexOfKey(name) >= 0) {
602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return ALREADY_EXISTS;
603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mFiles.add(name, file);
605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t AaptDir::addDir(const String8& name, const sp<AaptDir>& dir)
609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mDirs.indexOfKey(name) >= 0) {
611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return ALREADY_EXISTS;
612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mDirs.add(name, dir);
614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisp<AaptDir> AaptDir::makeDir(const String8& path)
618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String8 name;
620282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String8 remain = path;
621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<AaptDir> subdir = this;
623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (name = remain.walkPath(&remain), remain != "") {
624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        subdir = subdir->makeDir(name);
625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
626282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
627282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t i = subdir->mDirs.indexOfKey(name);
628282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (i >= 0) {
629282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return subdir->mDirs.valueAt(i);
630282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
631282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<AaptDir> dir = new AaptDir(name, subdir->mPath.appendPathCopy(name));
632282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    subdir->mDirs.add(name, dir);
633282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return dir;
634282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid AaptDir::removeFile(const String8& name)
637282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mFiles.removeItem(name);
639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid AaptDir::removeDir(const String8& name)
642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mDirs.removeItem(name);
644282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
645282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
64609384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinskistatus_t AaptDir::addLeafFile(const String8& leafName, const sp<AaptFile>& file,
64709384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski        const bool overwrite)
648282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<AaptGroup> group;
650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mFiles.indexOfKey(leafName) >= 0) {
651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        group = mFiles.valueFor(leafName);
652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        group = new AaptGroup(leafName, mPath.appendPathCopy(leafName));
654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mFiles.add(leafName, group);
655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
65709384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski    return group->addFile(file, overwrite);
658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskissize_t AaptDir::slurpFullTree(Bundle* bundle, const String8& srcDir,
661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            const AaptGroupEntry& kind, const String8& resType,
66209384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski                            sp<FilePathStore>& fullResPaths, const bool overwrite)
663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Vector<String8> fileNames;
665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    {
666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        DIR* dir = NULL;
667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dir = opendir(srcDir.string());
669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (dir == NULL) {
670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: opendir(%s): %s\n", srcDir.string(), strerror(errno));
671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return UNKNOWN_ERROR;
672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        /*
675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         * Slurp the filenames out of the directory.
676282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         */
677282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        while (1) {
678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            struct dirent* entry;
679282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
680282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            entry = readdir(dir);
681282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (entry == NULL)
682282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                break;
683282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
684282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (isHidden(srcDir.string(), entry->d_name))
685282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
686282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
687282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 name(entry->d_name);
688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fileNames.add(name);
689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Add fully qualified path for dependency purposes
690282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // if we're collecting them
691282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (fullResPaths != NULL) {
692282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fullResPaths->add(srcDir.appendPathCopy(name));
693282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
694282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        closedir(dir);
696282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t count = 0;
699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
700282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*
701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Stash away the files and recursively descend into subdirectories.
702282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
703282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t N = fileNames.size();
704282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t i;
705282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (i = 0; i < N; i++) {
706282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String8 pathName(srcDir);
707282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        FileType type;
708282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
709282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        pathName.appendPath(fileNames[i].string());
710282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        type = getFileType(pathName.string());
711282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (type == kFileTypeDirectory) {
712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<AaptDir> subdir;
713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool notAdded = false;
714282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (mDirs.indexOfKey(fileNames[i]) >= 0) {
715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                subdir = mDirs.valueFor(fileNames[i]);
716282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
717282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                subdir = new AaptDir(fileNames[i], mPath.appendPathCopy(fileNames[i]));
718282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                notAdded = true;
719282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
720282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ssize_t res = subdir->slurpFullTree(bundle, pathName, kind,
72109384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski                                                resType, fullResPaths, overwrite);
722282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (res < NO_ERROR) {
723282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return res;
724282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
725282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (res > 0 && notAdded) {
726282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                mDirs.add(fileNames[i], subdir);
727282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
728282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            count += res;
729282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else if (type == kFileTypeRegular) {
730282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<AaptFile> file = new AaptFile(pathName, kind, resType);
73109384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski            status_t err = addLeafFile(fileNames[i], file, overwrite);
732282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (err != NO_ERROR) {
733282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return err;
734282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
735282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
736282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            count++;
737282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
738282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
739282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (bundle->getVerbose())
740282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("   (ignoring non-file/dir '%s')\n", pathName.string());
741282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
742282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
743282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
744282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return count;
745282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
746282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
747282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t AaptDir::validate() const
748282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
749282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t NF = mFiles.size();
750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t ND = mDirs.size();
751282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t i;
752282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (i = 0; i < NF; i++) {
753282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!validateFileName(mFiles.valueAt(i)->getLeaf().string())) {
754282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            SourcePos(mFiles.valueAt(i)->getPrintableSource(), -1).error(
755282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    "Invalid filename.  Unable to add.");
756282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return UNKNOWN_ERROR;
757282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
758282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
759282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        size_t j;
760282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (j = i+1; j < NF; j++) {
761282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (strcasecmp(mFiles.valueAt(i)->getLeaf().string(),
762282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           mFiles.valueAt(j)->getLeaf().string()) == 0) {
763282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos(mFiles.valueAt(i)->getPrintableSource(), -1).error(
764282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "File is case-insensitive equivalent to: %s",
765282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        mFiles.valueAt(j)->getPrintableSource().string());
766282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return UNKNOWN_ERROR;
767282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
768282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
769282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // TODO: if ".gz", check for non-.gz; if non-, check for ".gz"
770282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // (this is mostly caught by the "marked" stuff, below)
771282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (j = 0; j < ND; j++) {
774282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (strcasecmp(mFiles.valueAt(i)->getLeaf().string(),
775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           mDirs.valueAt(j)->getLeaf().string()) == 0) {
776282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos(mFiles.valueAt(i)->getPrintableSource(), -1).error(
777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "File conflicts with dir from: %s",
778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        mDirs.valueAt(j)->getPrintableSource().string());
779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return UNKNOWN_ERROR;
780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
782282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
784282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (i = 0; i < ND; i++) {
785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!validateFileName(mDirs.valueAt(i)->getLeaf().string())) {
786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            SourcePos(mDirs.valueAt(i)->getPrintableSource(), -1).error(
787282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    "Invalid directory name, unable to add.");
788282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return UNKNOWN_ERROR;
789282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
790282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
791282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        size_t j;
792282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (j = i+1; j < ND; j++) {
793282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (strcasecmp(mDirs.valueAt(i)->getLeaf().string(),
794282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           mDirs.valueAt(j)->getLeaf().string()) == 0) {
795282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos(mDirs.valueAt(i)->getPrintableSource(), -1).error(
796282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "Directory is case-insensitive equivalent to: %s",
797282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        mDirs.valueAt(j)->getPrintableSource().string());
798282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return UNKNOWN_ERROR;
799282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
801282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
802282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        status_t err = mDirs.valueAt(i)->validate();
803282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != NO_ERROR) {
804282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return err;
805282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
806282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
807282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
808282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
809282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
810282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
811282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid AaptDir::print(const String8& prefix) const
812282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
813282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t ND=getDirs().size();
814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t i;
815282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (i=0; i<ND; i++) {
816282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        getDirs().valueAt(i)->print(prefix);
817282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
818282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
819282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t NF=getFiles().size();
820282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (i=0; i<NF; i++) {
821282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        getFiles().valueAt(i)->print(prefix);
822282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
823282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
824282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
825282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiString8 AaptDir::getPrintableSource() const
826282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
827282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mFiles.size() > 0) {
828282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Arbitrarily pull the first file out of the list as the source dir.
829282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return mFiles.valueAt(0)->getPrintableSource().getPathDir();
830282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
831282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mDirs.size() > 0) {
832282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Or arbitrarily pull the first dir out of the list as the source dir.
833282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return mDirs.valueAt(0)->getPrintableSource().getPathDir();
834282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
835282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
836282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Should never hit this case, but to be safe...
837282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return mPath;
838282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
839282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
840282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
841282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =========================================================================
842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =========================================================================
843282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =========================================================================
844282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
845282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t AaptSymbols::applyJavaSymbols(const sp<AaptSymbols>& javaSymbols)
846282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
847282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = NO_ERROR;
848282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t N = javaSymbols->mSymbols.size();
849282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (size_t i=0; i<N; i++) {
850282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String8& name = javaSymbols->mSymbols.keyAt(i);
851282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const AaptSymbolEntry& entry = javaSymbols->mSymbols.valueAt(i);
852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ssize_t pos = mSymbols.indexOfKey(name);
853282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (pos < 0) {
854282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            entry.sourcePos.error("Symbol '%s' declared with <java-symbol> not defined\n", name.string());
855282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            err = UNKNOWN_ERROR;
856282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
857282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
858282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //printf("**** setting symbol #%d/%d %s to isJavaSymbol=%d\n",
859282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //        i, N, name.string(), entry.isJavaSymbol ? 1 : 0);
860282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mSymbols.editValueAt(pos).isJavaSymbol = entry.isJavaSymbol;
861282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
862282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
863282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    N = javaSymbols->mNestedSymbols.size();
864282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (size_t i=0; i<N; i++) {
865282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String8& name = javaSymbols->mNestedSymbols.keyAt(i);
866282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const sp<AaptSymbols>& symbols = javaSymbols->mNestedSymbols.valueAt(i);
867282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ssize_t pos = mNestedSymbols.indexOfKey(name);
868282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (pos < 0) {
869282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            SourcePos pos;
870282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            pos.error("Java symbol dir %s not defined\n", name.string());
871282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            err = UNKNOWN_ERROR;
872282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
873282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
874282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //printf("**** applying java symbols in dir %s\n", name.string());
875282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        status_t myerr = mNestedSymbols.valueAt(pos)->applyJavaSymbols(symbols);
876282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (myerr != NO_ERROR) {
877282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            err = myerr;
878282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
879282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
880282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
881282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return err;
882282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
883282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
884282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =========================================================================
885282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =========================================================================
886282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =========================================================================
887282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
888282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiAaptAssets::AaptAssets()
889282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    : AaptDir(String8(), String8()),
89091447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath      mHavePrivateSymbols(false),
89191447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath      mChanged(false), mHaveIncludedAssets(false),
892fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski      mRes(NULL) {}
893282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
894282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiconst SortedVector<AaptGroupEntry>& AaptAssets::getGroupEntries() const {
895282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mChanged) {
896282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
897282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return mGroupEntries;
898282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
899282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
900282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t AaptAssets::addFile(const String8& name, const sp<AaptGroup>& file)
901282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
902282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mChanged = true;
903282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return AaptDir::addFile(name, file);
904282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
905282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
906282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisp<AaptFile> AaptAssets::addFile(
907282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String8& filePath, const AaptGroupEntry& entry,
908282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String8& srcDir, sp<AaptGroup>* outGroup,
909282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String8& resType)
910282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
911282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<AaptDir> dir = this;
912282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<AaptGroup> group;
913282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<AaptFile> file;
914282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String8 root, remain(filePath), partialPath;
915282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (remain.length() > 0) {
916282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        root = remain.walkPath(&remain);
917282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        partialPath.appendPath(root);
918282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
919282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String8 rootStr(root);
920282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
921282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (remain.length() == 0) {
922282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ssize_t i = dir->getFiles().indexOfKey(rootStr);
923282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (i >= 0) {
924282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                group = dir->getFiles().valueAt(i);
925282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
926282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                group = new AaptGroup(rootStr, filePath);
927282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                status_t res = dir->addFile(rootStr, group);
928282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (res != NO_ERROR) {
929282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return NULL;
930282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
931282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
932282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            file = new AaptFile(srcDir.appendPathCopy(filePath), entry, resType);
933282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            status_t res = group->addFile(file);
934282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (res != NO_ERROR) {
935282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return NULL;
936282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
937282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            break;
938282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
939282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
940282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ssize_t i = dir->getDirs().indexOfKey(rootStr);
941282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (i >= 0) {
942282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                dir = dir->getDirs().valueAt(i);
943282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
944282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<AaptDir> subdir = new AaptDir(rootStr, partialPath);
945282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                status_t res = dir->addDir(rootStr, subdir);
946282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (res != NO_ERROR) {
947282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return NULL;
948282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
949282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                dir = subdir;
950282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
951282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
952282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
953282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
954282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mGroupEntries.add(entry);
955282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (outGroup) *outGroup = group;
956282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return file;
957282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
958282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
959282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid AaptAssets::addResource(const String8& leafName, const String8& path,
960282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                const sp<AaptFile>& file, const String8& resType)
961282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
962282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<AaptDir> res = AaptDir::makeDir(kResString);
963282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String8 dirname = file->getGroupEntry().toDirName(resType);
964282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<AaptDir> subdir = res->makeDir(dirname);
965282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<AaptGroup> grr = new AaptGroup(leafName, path);
966282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    grr->addFile(file);
967282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
968282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    subdir->addFile(leafName, grr);
969282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
970282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
971282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
972282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskissize_t AaptAssets::slurpFromArgs(Bundle* bundle)
973282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
974282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int count;
975282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int totalCount = 0;
976282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    FileType type;
977282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const Vector<const char *>& resDirs = bundle->getResourceSourceDirs();
978282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t dirCount =resDirs.size();
979282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<AaptAssets> current = this;
980282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
981282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const int N = bundle->getFileSpecCount();
982282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
983282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*
984282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * If a package manifest was specified, include that first.
985282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
986282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getAndroidManifestFile() != NULL) {
987282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // place at root of zip.
988282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String8 srcFile(bundle->getAndroidManifestFile());
989282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        addFile(srcFile.getPathLeaf(), AaptGroupEntry(), srcFile.getPathDir(),
990282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                NULL, String8());
991282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        totalCount++;
992282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
993282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
994282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*
995282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * If a directory of custom assets was supplied, slurp 'em up.
996282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
99709384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski    const Vector<const char*>& assetDirs = bundle->getAssetSourceDirs();
99809384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski    const int AN = assetDirs.size();
99909384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski    for (int i = 0; i < AN; i++) {
100009384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski        FileType type = getFileType(assetDirs[i]);
1001282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (type == kFileTypeNonexistent) {
100209384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski            fprintf(stderr, "ERROR: asset directory '%s' does not exist\n", assetDirs[i]);
1003282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return UNKNOWN_ERROR;
1004282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1005282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (type != kFileTypeDirectory) {
100609384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski            fprintf(stderr, "ERROR: '%s' is not a directory\n", assetDirs[i]);
1007282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return UNKNOWN_ERROR;
1008282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1009282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
101009384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski        String8 assetRoot(assetDirs[i]);
1011282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<AaptDir> assetAaptDir = makeDir(String8(kAssetDir));
1012282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        AaptGroupEntry group;
1013282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        count = assetAaptDir->slurpFullTree(bundle, assetRoot, group,
101409384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski                                            String8(), mFullAssetPaths, true);
1015282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (count < 0) {
1016282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            totalCount = count;
1017282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
1018282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1019282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (count > 0) {
1020282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mGroupEntries.add(group);
1021282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1022282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        totalCount += count;
1023282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
102409384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski        if (bundle->getVerbose()) {
1025282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("Found %d custom asset file%s in %s\n",
102609384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski                   count, (count==1) ? "" : "s", assetDirs[i]);
102709384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski        }
1028282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1029282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1030282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*
1031282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * If a directory of resource-specific assets was supplied, slurp 'em up.
1032282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
1033282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (size_t i=0; i<dirCount; i++) {
1034282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const char *res = resDirs[i];
1035282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (res) {
1036282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            type = getFileType(res);
1037282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (type == kFileTypeNonexistent) {
1038282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, "ERROR: resource directory '%s' does not exist\n", res);
1039282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return UNKNOWN_ERROR;
1040282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1041282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (type == kFileTypeDirectory) {
1042282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (i>0) {
1043282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sp<AaptAssets> nextOverlay = new AaptAssets();
1044282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    current->setOverlay(nextOverlay);
1045282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    current = nextOverlay;
1046282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    current->setFullResPaths(mFullResPaths);
1047282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1048282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                count = current->slurpResourceTree(bundle, String8(res));
10499ab9b93eae8b2fc747d6101cf0e4c19b2218715fBryan Mawhinney                if (i > 0 && count > 0) {
10509ab9b93eae8b2fc747d6101cf0e4c19b2218715fBryan Mawhinney                  count = current->filter(bundle);
10519ab9b93eae8b2fc747d6101cf0e4c19b2218715fBryan Mawhinney                }
1052282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1053282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (count < 0) {
1054282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    totalCount = count;
1055282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    goto bail;
1056282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1057282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                totalCount += count;
1058282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1059282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            else {
1060282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, "ERROR: '%s' is not a directory\n", res);
1061282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return UNKNOWN_ERROR;
1062282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1063282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1064282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1065282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1066282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*
1067282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Now do any additional raw files.
1068282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
1069282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (int arg=0; arg<N; arg++) {
1070282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const char* assetDir = bundle->getFileSpecEntry(arg);
1071282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1072282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        FileType type = getFileType(assetDir);
1073282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (type == kFileTypeNonexistent) {
1074282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: input directory '%s' does not exist\n", assetDir);
1075282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return UNKNOWN_ERROR;
1076282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1077282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (type != kFileTypeDirectory) {
1078282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: '%s' is not a directory\n", assetDir);
1079282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return UNKNOWN_ERROR;
1080282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1081282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1082282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String8 assetRoot(assetDir);
1083282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1084282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (bundle->getVerbose())
1085282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("Processing raw dir '%s'\n", (const char*) assetDir);
1086282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1087282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        /*
1088282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         * Do a recursive traversal of subdir tree.  We don't make any
1089282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         * guarantees about ordering, so we're okay with an inorder search
1090282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         * using whatever order the OS happens to hand back to us.
1091282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         */
1092282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        count = slurpFullTree(bundle, assetRoot, AaptGroupEntry(), String8(), mFullAssetPaths);
1093282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (count < 0) {
1094282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            /* failure; report error and remove archive */
1095282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            totalCount = count;
1096282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
1097282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1098282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        totalCount += count;
1099282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (bundle->getVerbose())
1101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("Found %d asset file%s in %s\n",
1102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                   count, (count==1) ? "" : "s", assetDir);
1103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    count = validate();
1106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (count != NO_ERROR) {
1107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        totalCount = count;
1108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
1109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    count = filter(bundle);
1112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (count != NO_ERROR) {
1113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        totalCount = count;
1114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
1115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail:
1118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return totalCount;
1119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskissize_t AaptAssets::slurpFullTree(Bundle* bundle, const String8& srcDir,
1122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    const AaptGroupEntry& kind,
1123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    const String8& resType,
112440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                                    sp<FilePathStore>& fullResPaths,
112540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                                    const bool overwrite)
1126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
112740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    ssize_t res = AaptDir::slurpFullTree(bundle, srcDir, kind, resType, fullResPaths, overwrite);
1128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (res > 0) {
1129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mGroupEntries.add(kind);
1130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return res;
1133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskissize_t AaptAssets::slurpResourceTree(Bundle* bundle, const String8& srcDir)
1136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t err = 0;
1138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    DIR* dir = opendir(srcDir.string());
1140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (dir == NULL) {
1141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: opendir(%s): %s\n", srcDir.string(), strerror(errno));
1142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
1143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t count = 0;
1146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*
1148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Run through the directory, looking for dirs that match the
1149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * expected pattern.
1150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
1151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (1) {
1152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        struct dirent* entry = readdir(dir);
1153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (entry == NULL) {
1154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            break;
1155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (isHidden(srcDir.string(), entry->d_name)) {
1158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
1159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String8 subdirName(srcDir);
1162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        subdirName.appendPath(entry->d_name);
1163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        AaptGroupEntry group;
1165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String8 resType;
1166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        bool b = group.initFromDirName(entry->d_name, &resType);
1167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!b) {
1168fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            fprintf(stderr, "invalid resource directory name: %s %s\n", srcDir.string(),
1169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    entry->d_name);
1170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            err = -1;
1171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
1172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (bundle->getMaxResVersion() != NULL && group.getVersionString().length() != 0) {
1175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int maxResInt = atoi(bundle->getMaxResVersion());
1176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const char *verString = group.getVersionString().string();
1177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int dirVersionInt = atoi(verString + 1); // skip 'v' in version name
1178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (dirVersionInt > maxResInt) {
1179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski              fprintf(stderr, "max res %d, skipping %s\n", maxResInt, entry->d_name);
1180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski              continue;
1181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        FileType type = getFileType(subdirName.string());
1185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (type == kFileTypeDirectory) {
1187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<AaptDir> dir = makeDir(resType);
1188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ssize_t res = dir->slurpFullTree(bundle, subdirName, group,
1189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                resType, mFullResPaths);
1190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (res < 0) {
1191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                count = res;
1192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                goto bail;
1193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (res > 0) {
1195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                mGroupEntries.add(group);
1196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                count += res;
1197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Only add this directory if we don't already have a resource dir
1200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // for the current type.  This ensures that we only add the dir once
1201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // for all configs.
1202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<AaptDir> rdir = resDir(resType);
1203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (rdir == NULL) {
1204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                mResDirs.add(dir);
1205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
1207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (bundle->getVerbose()) {
1208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, "   (ignoring file '%s')\n", subdirName.string());
1209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail:
1214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    closedir(dir);
1215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    dir = NULL;
1216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != 0) {
1218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return err;
1219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return count;
1221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskissize_t
12242412f84064c26b643c722ce914a97c4ec7776c69Andreas GampeAaptAssets::slurpResourceZip(Bundle* /* bundle */, const char* filename)
1225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int count = 0;
1227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    SortedVector<AaptGroupEntry> entries;
1228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ZipFile* zip = new ZipFile;
1230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = zip->open(filename, ZipFile::kOpenReadOnly);
1231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
1232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "error opening zip file %s\n", filename);
1233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        count = err;
1234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        delete zip;
1235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return -1;
1236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const int N = zip->getNumEntries();
1239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (int i=0; i<N; i++) {
1240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ZipEntry* entry = zip->getEntryByIndex(i);
1241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (entry->getDeleted()) {
1242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
1243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String8 entryName(entry->getFileName());
1246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String8 dirName = entryName.getPathDir();
1248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<AaptDir> dir = dirName == "" ? this : makeDir(dirName);
1249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String8 resType;
1251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        AaptGroupEntry kind;
1252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String8 remain;
1254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (entryName.walkPath(&remain) == kResourceDir) {
1255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // these are the resources, pull their type out of the directory name
1256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            kind.initFromDirName(remain.walkPath().string(), &resType);
1257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
1258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // these are untyped and don't have an AaptGroupEntry
1259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (entries.indexOf(kind) < 0) {
1261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            entries.add(kind);
1262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mGroupEntries.add(kind);
1263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // use the one from the zip file if they both exist.
1266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dir->removeFile(entryName.getPathLeaf());
1267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<AaptFile> file = new AaptFile(entryName, kind, resType);
1269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        status_t err = dir->addLeafFile(entryName.getPathLeaf(), file);
1270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != NO_ERROR) {
1271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "err=%s entryName=%s\n", strerror(err), entryName.string());
1272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            count = err;
1273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
1274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        file->setCompressionMethod(entry->getCompressionMethod());
1276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#if 0
1278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (entryName == "AndroidManifest.xml") {
1279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("AndroidManifest.xml\n");
1280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printf("\n\nfile: %s\n", entryName.string());
1282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif
1283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        size_t len = entry->getUncompressedLen();
1285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        void* data = zip->uncompress(entry);
1286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        void* buf = file->editData(len);
1287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        memcpy(buf, data, len);
1288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#if 0
1290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const int OFF = 0;
1291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const unsigned char* p = (unsigned char*)data;
1292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const unsigned char* end = p+len;
1293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        p += OFF;
1294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (int i=0; i<32 && p < end; i++) {
1295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("0x%03x ", i*0x10 + OFF);
1296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (int j=0; j<0x10 && p < end; j++) {
1297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf(" %02x", *p);
1298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                p++;
1299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("\n");
1301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif
1303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        free(data);
1305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        count++;
1307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail:
1310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    delete zip;
1311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return count;
1312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t AaptAssets::filter(Bundle* bundle)
1315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1316fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    WeakResourceFilter reqFilter;
1317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = reqFilter.parse(bundle->getConfigurations());
1318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
1319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return err;
1320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1322fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    uint32_t preferredDensity = 0;
1323fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (bundle->getPreferredDensity().size() > 0) {
1324fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        ResTable_config preferredConfig;
1325fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        if (!AaptConfig::parseDensity(bundle->getPreferredDensity().string(), &preferredConfig)) {
1326fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            fprintf(stderr, "Error parsing preferred density: %s\n",
1327fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    bundle->getPreferredDensity().string());
1328fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            return UNKNOWN_ERROR;
1329fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        }
1330fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        preferredDensity = preferredConfig.density;
1331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1333fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (reqFilter.isEmpty() && preferredDensity == 0) {
1334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NO_ERROR;
1335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getVerbose()) {
1338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!reqFilter.isEmpty()) {
1339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("Applying required filter: %s\n",
1340fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    bundle->getConfigurations().string());
1341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1342fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        if (preferredDensity > 0) {
1343fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            printf("Applying preferred density filter: %s\n",
1344fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    bundle->getPreferredDensity().string());
1345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const Vector<sp<AaptDir> >& resdirs = mResDirs;
1349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t ND = resdirs.size();
1350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (size_t i=0; i<ND; i++) {
1351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const sp<AaptDir>& dir = resdirs.itemAt(i);
1352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (dir->getLeaf() == kValuesDir) {
1353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // The "value" dir is special since a single file defines
1354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // multiple resources, so we can not do filtering on the
1355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // files themselves.
1356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
1357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (dir->getLeaf() == kMipmapDir) {
1359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // We also skip the "mipmap" directory, since the point of this
1360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // is to include all densities without stripping.  If you put
1361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // other configurations in here as well they won't be stripped
1362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // either...  So don't do that.  Seriously.  What is wrong with you?
1363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
1364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t NG = dir->getFiles().size();
1367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (size_t j=0; j<NG; j++) {
1368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<AaptGroup> grp = dir->getFiles().valueAt(j);
1369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // First remove any configurations we know we don't need.
1371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t k=0; k<grp->getFiles().size(); k++) {
1372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<AaptFile> file = grp->getFiles().valueAt(k);
1373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (k == 0 && grp->getFiles().size() == 1) {
1374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // If this is the only file left, we need to keep it.
1375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // Otherwise the resource IDs we are using will be inconsistent
1376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // with what we get when not stripping.  Sucky, but at least
1377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // for now we can rely on the back-end doing another filtering
1378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // pass to take this out and leave us with this resource name
1379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // containing no entries.
1380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
1381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (file->getPath().getPathExtension() == ".xml") {
1383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // We can't remove .xml files at this point, because when
1384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // we parse them they may add identifier resources, so
1385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // removing them can cause our resource identifiers to
1386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // become inconsistent.
1387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
1388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                const ResTable_config& config(file->getGroupEntry().toParams());
1390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!reqFilter.match(config)) {
1391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (bundle->getVerbose()) {
1392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        printf("Pruning unneeded resource: %s\n",
1393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                file->getPrintableSource().string());
1394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    grp->removeFile(k);
1396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    k--;
1397282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1398282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Quick check: no preferred filters, nothing more to do.
1401fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            if (preferredDensity == 0) {
1402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
1403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
14058cf61845187e301dfc4f64b42921977d38766a34Adam Lesinski            // Get the preferred density if there is one. We do not match exactly for density.
14068cf61845187e301dfc4f64b42921977d38766a34Adam Lesinski            // If our preferred density is hdpi but we only have mdpi and xhdpi resources, we
14078cf61845187e301dfc4f64b42921977d38766a34Adam Lesinski            // pick xhdpi.
1408fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            for (size_t k=0; k<grp->getFiles().size(); k++) {
1409fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                sp<AaptFile> file = grp->getFiles().valueAt(k);
1410fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                if (k == 0 && grp->getFiles().size() == 1) {
1411fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    // If this is the only file left, we need to keep it.
1412fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    // Otherwise the resource IDs we are using will be inconsistent
1413fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    // with what we get when not stripping.  Sucky, but at least
1414fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    // for now we can rely on the back-end doing another filtering
1415fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    // pass to take this out and leave us with this resource name
1416fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    // containing no entries.
1417fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    continue;
1418fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                }
1419fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                if (file->getPath().getPathExtension() == ".xml") {
1420fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    // We can't remove .xml files at this point, because when
1421fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    // we parse them they may add identifier resources, so
1422fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    // removing them can cause our resource identifiers to
1423fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    // become inconsistent.
1424fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    continue;
1425fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                }
1426fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                const ResTable_config& config(file->getGroupEntry().toParams());
1427fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                if (config.density != 0 && config.density != preferredDensity) {
1428fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    // This is a resource we would prefer not to have.  Check
1429fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    // to see if have a similar variation that we would like
1430fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    // to have and, if so, we can drop it.
1431fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    uint32_t bestDensity = config.density;
1432fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski
1433fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    for (size_t m=0; m<grp->getFiles().size(); m++) {
1434fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                        if (m == k) {
1435fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                            continue;
1436fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                        }
14378cf61845187e301dfc4f64b42921977d38766a34Adam Lesinski
1438fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                        sp<AaptFile> mfile = grp->getFiles().valueAt(m);
1439fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                        const ResTable_config& mconfig(mfile->getGroupEntry().toParams());
1440fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                        if (AaptConfig::isSameExcept(config, mconfig, ResTable_config::CONFIG_DENSITY)) {
1441fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                            // See if there is a better density resource
1442fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                            if (mconfig.density < bestDensity &&
1443b0db8de73e6e4151b4e9d1fe3be1f609c3c1fb83Bryan Mawhinney                                    mconfig.density >= preferredDensity &&
1444fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                                    bestDensity > preferredDensity) {
1445b0db8de73e6e4151b4e9d1fe3be1f609c3c1fb83Bryan Mawhinney                                // This density is our preferred density, or between our best density and
1446fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                                // the preferred density, therefore it is better.
1447fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                                bestDensity = mconfig.density;
1448fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                            } else if (mconfig.density > bestDensity &&
1449fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                                    bestDensity < preferredDensity) {
1450fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                                // This density is better than our best density and
1451fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                                // our best density was smaller than our preferred
1452fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                                // density, so it is better.
1453fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                                bestDensity = mconfig.density;
1454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1456fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    }
14578cf61845187e301dfc4f64b42921977d38766a34Adam Lesinski
1458fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    if (bestDensity != config.density) {
1459fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                        if (bundle->getVerbose()) {
1460fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                            printf("Pruning unneeded resource: %s\n",
1461fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                                    file->getPrintableSource().string());
14628cf61845187e301dfc4f64b42921977d38766a34Adam Lesinski                        }
1463fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                        grp->removeFile(k);
1464fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                        k--;
1465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
1472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisp<AaptSymbols> AaptAssets::getSymbolsFor(const String8& name)
1475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<AaptSymbols> sym = mSymbols.valueFor(name);
1477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (sym == NULL) {
1478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sym = new AaptSymbols();
1479282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mSymbols.add(name, sym);
1480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return sym;
1482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisp<AaptSymbols> AaptAssets::getJavaSymbolsFor(const String8& name)
1485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<AaptSymbols> sym = mJavaSymbols.valueFor(name);
1487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (sym == NULL) {
1488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sym = new AaptSymbols();
1489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mJavaSymbols.add(name, sym);
1490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return sym;
1492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t AaptAssets::applyJavaSymbols()
1495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t N = mJavaSymbols.size();
1497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (size_t i=0; i<N; i++) {
1498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String8& name = mJavaSymbols.keyAt(i);
1499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const sp<AaptSymbols>& symbols = mJavaSymbols.valueAt(i);
1500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ssize_t pos = mSymbols.indexOfKey(name);
1501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (pos < 0) {
1502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            SourcePos pos;
1503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            pos.error("Java symbol dir %s not defined\n", name.string());
1504282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return UNKNOWN_ERROR;
1505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //printf("**** applying java symbols in dir %s\n", name.string());
1507282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        status_t err = mSymbols.valueAt(pos)->applyJavaSymbols(symbols);
1508282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != NO_ERROR) {
1509282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return err;
1510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1511282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1512282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1513282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
1514282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1515282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1516282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool AaptAssets::isJavaSymbol(const AaptSymbolEntry& sym, bool includePrivate) const {
1517282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //printf("isJavaSymbol %s: public=%d, includePrivate=%d, isJavaSymbol=%d\n",
1518282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //        sym.name.string(), sym.isPublic ? 1 : 0, includePrivate ? 1 : 0,
1519282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //        sym.isJavaSymbol ? 1 : 0);
1520282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (!mHavePrivateSymbols) return true;
1521282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (sym.isPublic) return true;
1522282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (includePrivate && sym.isJavaSymbol) return true;
1523282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
1524282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1525282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1526282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t AaptAssets::buildIncludedResources(Bundle* bundle)
1527282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1528833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    if (mHaveIncludedAssets) {
1529833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        return NO_ERROR;
1530833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    }
1531833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski
1532833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    // Add in all includes.
1533833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    const Vector<String8>& includes = bundle->getPackageIncludes();
1534833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    const size_t packageIncludeCount = includes.size();
1535833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    for (size_t i = 0; i < packageIncludeCount; i++) {
1536833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        if (bundle->getVerbose()) {
1537833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            printf("Including resources from package: %s\n", includes[i].string());
1538833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        }
1539833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski
1540833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        if (!mIncludedAssets.addAssetPath(includes[i], NULL)) {
1541833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            fprintf(stderr, "ERROR: Asset package include '%s' not found.\n",
1542833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                    includes[i].string());
1543833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            return UNKNOWN_ERROR;
1544282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1545282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1546282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1547833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    const String8& featureOfBase = bundle->getFeatureOfPackage();
1548833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    if (!featureOfBase.isEmpty()) {
1549833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        if (bundle->getVerbose()) {
1550833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            printf("Including base feature resources from package: %s\n",
1551833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                    featureOfBase.string());
1552833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        }
1553833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski
1554833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        if (!mIncludedAssets.addAssetPath(featureOfBase, NULL)) {
1555833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            fprintf(stderr, "ERROR: base feature package '%s' not found.\n",
1556833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                    featureOfBase.string());
1557833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            return UNKNOWN_ERROR;
1558833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        }
1559833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    }
1560833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski
1561833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    mHaveIncludedAssets = true;
1562833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski
1563282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
1564282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1565282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1566282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t AaptAssets::addIncludedResources(const sp<AaptFile>& file)
1567282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1568282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const ResTable& res = getIncludedResources();
1569282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // XXX dirty!
157000b314436f4fdfada4bbf1e79ec12e9fa38aeaf1Narayan Kamath    return const_cast<ResTable&>(res).add(file->getData(), file->getSize());
1571282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiconst ResTable& AaptAssets::getIncludedResources() const
1574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return mIncludedAssets.getResources(false);
1576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1578ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam LesinskiAssetManager& AaptAssets::getAssetManager()
1579ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski{
1580ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski    return mIncludedAssets;
1581ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski}
1582ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski
1583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid AaptAssets::print(const String8& prefix) const
1584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String8 innerPrefix(prefix);
1586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    innerPrefix.append("  ");
1587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String8 innerInnerPrefix(innerPrefix);
1588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    innerInnerPrefix.append("  ");
1589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    printf("%sConfigurations:\n", prefix.string());
1590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t N=mGroupEntries.size();
1591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (size_t i=0; i<N; i++) {
1592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String8 cname = mGroupEntries.itemAt(i).toDirName(String8());
1593282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printf("%s %s\n", prefix.string(),
1594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                cname != "" ? cname.string() : "(default)");
1595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    printf("\n%sFiles:\n", prefix.string());
1598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    AaptDir::print(innerPrefix);
1599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    printf("\n%sResource Dirs:\n", prefix.string());
1601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const Vector<sp<AaptDir> >& resdirs = mResDirs;
1602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t NR = resdirs.size();
1603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (size_t i=0; i<NR; i++) {
1604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const sp<AaptDir>& d = resdirs.itemAt(i);
1605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printf("%s  Type %s\n", prefix.string(), d->getLeaf().string());
1606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d->print(innerInnerPrefix);
1607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisp<AaptDir> AaptAssets::resDir(const String8& name) const
1611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const Vector<sp<AaptDir> >& resdirs = mResDirs;
1613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t N = resdirs.size();
1614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (size_t i=0; i<N; i++) {
1615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const sp<AaptDir>& d = resdirs.itemAt(i);
1616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d->getLeaf() == name) {
1617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return d;
1618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1620282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NULL;
1621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool
1624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivalid_symbol_name(const String8& symbol)
1625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1626282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    static char const * const KEYWORDS[] = {
1627282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        "abstract", "assert", "boolean", "break",
1628282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        "byte", "case", "catch", "char", "class", "const", "continue",
1629282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        "default", "do", "double", "else", "enum", "extends", "final",
1630282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        "finally", "float", "for", "goto", "if", "implements", "import",
1631282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        "instanceof", "int", "interface", "long", "native", "new", "package",
1632282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        "private", "protected", "public", "return", "short", "static",
1633282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        "strictfp", "super", "switch", "synchronized", "this", "throw",
1634282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        "throws", "transient", "try", "void", "volatile", "while",
1635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        "true", "false", "null",
1636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        NULL
1637282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    };
1638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char*const* k = KEYWORDS;
1639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char*const s = symbol.string();
1640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (*k) {
1641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (0 == strcmp(s, *k)) {
1642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;
1643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1644282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        k++;
1645282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return true;
1647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1648