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* kDefaultLocale = "default";
19282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char* kAssetDir = "assets";
20282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char* kResourceDir = "res";
21282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char* kValuesDir = "values";
22282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char* kMipmapDir = "mipmap";
23282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char* kInvalidChars = "/\\:";
24282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const size_t kMaxAssetFileName = 100;
25282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
26282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const String8 kResString(kResourceDir);
27282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
28282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
29282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Names of asset files must meet the following criteria:
30282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
31282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *  - the filename length must be less than kMaxAssetFileName bytes long
32282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *    (and can't be empty)
33282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *  - all characters must be 7-bit printable ASCII
34282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *  - none of { '/' '\\' ':' }
35282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
36282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Pass in just the filename, not the full path.
37282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
38282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic bool validateFileName(const char* fileName)
39282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
40282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char* cp = fileName;
41282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t len = 0;
42282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
43282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (*cp != '\0') {
44282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if ((*cp & 0x80) != 0)
45282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;           // reject high ASCII
46282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (*cp < 0x20 || *cp >= 0x7f)
47282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;           // reject control chars and 0x7f
48282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (strchr(kInvalidChars, *cp) != NULL)
49282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;           // reject path sep chars
50282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        cp++;
51282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        len++;
52282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
53282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
54282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (len < 1 || len > kMaxAssetFileName)
55282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return false;               // reject empty or too long
56282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
57282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return true;
58282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
59282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
60282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// The default to use if no other ignore pattern is defined.
61282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiconst char * const gDefaultIgnoreAssets =
62282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    "!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~";
63282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// The ignore pattern that can be passed via --ignore-assets in Main.cpp
64282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiconst char * gUserIgnoreAssets = NULL;
65282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
66282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic bool isHidden(const char *root, const char *path)
67282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
68282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Patterns syntax:
69282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // - Delimiter is :
70282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // - Entry can start with the flag ! to avoid printing a warning
71282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //   about the file being ignored.
72282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // - Entry can have the flag "<dir>" to match only directories
73282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //   or <file> to match only files. Default is to match both.
74282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // - Entry can be a simplified glob "<prefix>*" or "*<suffix>"
75282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //   where prefix/suffix must have at least 1 character (so that
76282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //   we don't match a '*' catch-all pattern.)
77282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // - The special filenames "." and ".." are always ignored.
78282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // - Otherwise the full string is matched.
79282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // - match is not case-sensitive.
80282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
81282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (strcmp(path, ".") == 0 || strcmp(path, "..") == 0) {
82282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
83282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
84282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
85282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char *delim = ":";
86282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char *p = gUserIgnoreAssets;
87282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (!p || !p[0]) {
88282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        p = getenv("ANDROID_AAPT_IGNORE");
89282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
90282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (!p || !p[0]) {
91282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        p = gDefaultIgnoreAssets;
92282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
93282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    char *patterns = strdup(p);
94282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
95282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool ignore = false;
96282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool chatty = true;
97282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    char *matchedPattern = NULL;
98282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
99282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String8 fullPath(root);
100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fullPath.appendPath(path);
101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    FileType type = getFileType(fullPath);
102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int plen = strlen(path);
104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Note: we don't have strtok_r under mingw.
106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for(char *token = strtok(patterns, delim);
107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            !ignore && token != NULL;
108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            token = strtok(NULL, delim)) {
109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        chatty = token[0] != '!';
110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!chatty) token++; // skip !
111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (strncasecmp(token, "<dir>" , 5) == 0) {
112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (type != kFileTypeDirectory) continue;
113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            token += 5;
114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (strncasecmp(token, "<file>", 6) == 0) {
116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (type != kFileTypeRegular) continue;
117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            token += 6;
118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        matchedPattern = token;
121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int n = strlen(token);
122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (token[0] == '*') {
124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Match *suffix
125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            token++;
126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            n--;
127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (n <= plen) {
128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ignore = strncasecmp(token, path + plen - n, n) == 0;
129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else if (n > 1 && token[n - 1] == '*') {
131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Match prefix*
132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ignore = strncasecmp(token, path, n - 1) == 0;
133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ignore = strcasecmp(token, path) == 0;
135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (ignore && chatty) {
139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "    (skipping %s '%s' due to ANDROID_AAPT_IGNORE pattern '%s')\n",
140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                type == kFileTypeDirectory ? "dir" : "file",
141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                path,
142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                matchedPattern ? matchedPattern : "");
143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    free(patterns);
146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return ignore;
147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =========================================================================
150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =========================================================================
151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =========================================================================
152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
15391447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath/* static */
15491447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamathinline bool isAlpha(const String8& string) {
15591447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath     const size_t length = string.length();
15691447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath     for (size_t i = 0; i < length; ++i) {
15791447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath          if (!isalpha(string[i])) {
15891447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath              return false;
15991447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath          }
16091447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath     }
16191447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath
16291447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath     return true;
16391447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath}
16491447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath
16591447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath/* static */
16691447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamathinline bool isNumber(const String8& string) {
16791447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath     const size_t length = string.length();
16891447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath     for (size_t i = 0; i < length; ++i) {
16991447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath          if (!isdigit(string[i])) {
17091447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath              return false;
17191447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath          }
17291447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath     }
17391447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath
17491447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath     return true;
17591447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath}
17691447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath
17791447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamathvoid AaptLocaleValue::setLanguage(const char* languageChars) {
17891447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath     size_t i = 0;
17991447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath     while ((*languageChars) != '\0') {
18091447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath          language[i++] = tolower(*languageChars);
18191447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath          languageChars++;
18291447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath     }
18391447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath}
18491447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath
18591447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamathvoid AaptLocaleValue::setRegion(const char* regionChars) {
18691447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath    size_t i = 0;
18791447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath    while ((*regionChars) != '\0') {
18891447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath         region[i++] = toupper(*regionChars);
18991447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath         regionChars++;
19091447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath    }
19191447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath}
19291447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath
19391447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamathvoid AaptLocaleValue::setScript(const char* scriptChars) {
19491447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath    size_t i = 0;
19591447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath    while ((*scriptChars) != '\0') {
19691447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath         if (i == 0) {
19791447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath             script[i++] = toupper(*scriptChars);
19891447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath         } else {
19991447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath             script[i++] = tolower(*scriptChars);
20091447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath         }
20191447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath         scriptChars++;
20291447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath    }
20391447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath}
20491447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath
20591447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamathvoid AaptLocaleValue::setVariant(const char* variantChars) {
20691447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath     size_t i = 0;
20791447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath     while ((*variantChars) != '\0') {
20891447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath          variant[i++] = *variantChars;
20991447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath          variantChars++;
21091447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath     }
21191447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath}
21291447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath
21391447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamathbool AaptLocaleValue::initFromFilterString(const String8& str) {
21491447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath     // A locale (as specified in the filter) is an underscore separated name such
21591447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath     // as "en_US", "en_Latn_US", or "en_US_POSIX".
216fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     Vector<String8> parts = AaptUtil::splitAndLowerCase(str, '_');
21791447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath
21891447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath     const int numTags = parts.size();
21991447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath     bool valid = false;
22091447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath     if (numTags >= 1) {
22191447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath         const String8& lang = parts[0];
22291447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath         if (isAlpha(lang) && (lang.length() == 2 || lang.length() == 3)) {
22391447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath             setLanguage(lang.string());
22491447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath             valid = true;
22591447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath         }
22691447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath     }
22791447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath
22891447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath     if (!valid || numTags == 1) {
229fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski         return valid;
230fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     }
231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
232fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     // At this point, valid == true && numTags > 1.
233fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     const String8& part2 = parts[1];
234fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     if ((part2.length() == 2 && isAlpha(part2)) ||
235fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski         (part2.length() == 3 && isNumber(part2))) {
236fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski         setRegion(part2.string());
237fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     } else if (part2.length() == 4 && isAlpha(part2)) {
238fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski         setScript(part2.string());
239fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     } else if (part2.length() >= 5 && part2.length() <= 8) {
240fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski         setVariant(part2.string());
241fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     } else {
242fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski         valid = false;
243fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     }
244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
245fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     if (!valid || numTags == 2) {
246fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski         return valid;
247fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     }
248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
249fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     // At this point, valid == true && numTags > 1.
250fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     const String8& part3 = parts[2];
251fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     if (((part3.length() == 2 && isAlpha(part3)) ||
252fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski         (part3.length() == 3 && isNumber(part3))) && script[0]) {
253fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski         setRegion(part3.string());
254fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     } else if (part3.length() >= 5 && part3.length() <= 8) {
255fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski         setVariant(part3.string());
256fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     } else {
257fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski         valid = false;
258fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     }
259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
260fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     if (!valid || numTags == 3) {
261fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski         return valid;
262fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     }
263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
264fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     const String8& part4 = parts[3];
265fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     if (part4.length() >= 5 && part4.length() <= 8) {
266fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski         setVariant(part4.string());
267fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     } else {
268fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski         valid = false;
269fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     }
270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
271fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     if (!valid || numTags > 4) {
272fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski         return false;
273fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     }
274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
275fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski     return true;
276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
278fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinskiint AaptLocaleValue::initFromDirName(const Vector<String8>& parts, const int startIndex) {
279fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    const int size = parts.size();
280fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    int currentIndex = startIndex;
281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
282fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    String8 part = parts[currentIndex];
283fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (part[0] == 'b' && part[1] == '+') {
284fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        // This is a "modified" BCP-47 language tag. Same semantics as BCP-47 tags,
285fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        // except that the separator is "+" and not "-".
286fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        Vector<String8> subtags = AaptUtil::splitAndLowerCase(part, '+');
287fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        subtags.removeItemsAt(0);
288fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        if (subtags.size() == 1) {
289fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            setLanguage(subtags[0]);
290fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        } else if (subtags.size() == 2) {
291fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            setLanguage(subtags[0]);
292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
293fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            // The second tag can either be a region, a variant or a script.
294fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            switch (subtags[1].size()) {
295fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                case 2:
296fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                case 3:
297fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    setRegion(subtags[1]);
298fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    break;
299fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                case 4:
300fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    setScript(subtags[1]);
301fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    break;
302fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                case 5:
303fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                case 6:
304fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                case 7:
305fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                case 8:
306fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    setVariant(subtags[1]);
307fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    break;
308fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                default:
309fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    fprintf(stderr, "ERROR: Invalid BCP-47 tag in directory name %s\n",
310fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                            part.string());
311fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    return -1;
312fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            }
313fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        } else if (subtags.size() == 3) {
314fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            // The language is always the first subtag.
315fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            setLanguage(subtags[0]);
316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
317fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            // The second subtag can either be a script or a region code.
318fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            // If its size is 4, it's a script code, else it's a region code.
319fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            bool hasRegion = false;
320fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            if (subtags[1].size() == 4) {
321fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                setScript(subtags[1]);
322fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            } else if (subtags[1].size() == 2 || subtags[1].size() == 3) {
323fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                setRegion(subtags[1]);
324fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                hasRegion = true;
325fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            } else {
326fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                fprintf(stderr, "ERROR: Invalid BCP-47 tag in directory name %s\n", part.string());
327fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                return -1;
328fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            }
329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
330fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            // The third tag can either be a region code (if the second tag was
331fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            // a script), else a variant code.
332fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            if (subtags[2].size() > 4) {
333fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                setVariant(subtags[2]);
334fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            } else {
335fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                setRegion(subtags[2]);
336fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            }
337fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        } else if (subtags.size() == 4) {
338fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            setLanguage(subtags[0]);
339fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            setScript(subtags[1]);
340fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            setRegion(subtags[2]);
341fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            setVariant(subtags[3]);
342fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        } else {
343fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            fprintf(stderr, "ERROR: Invalid BCP-47 tag in directory name: %s\n", part.string());
344fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            return -1;
345fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        }
346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
347fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        return ++currentIndex;
348fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    } else {
349fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        if ((part.length() == 2 || part.length() == 3) && isAlpha(part)) {
350fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            setLanguage(part);
351fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            if (++currentIndex == size) {
352fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                return size;
353fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            }
354fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        } else {
355fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            return currentIndex;
356fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        }
357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
358fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        part = parts[currentIndex];
359fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        if (part.string()[0] == 'r' && part.length() == 3) {
360fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            setRegion(part.string() + 1);
361fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            if (++currentIndex == size) {
362fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                return size;
363fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            }
364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
367fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    return currentIndex;
368fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski}
369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
371fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam LesinskiString8 AaptLocaleValue::toDirName() const {
372fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    String8 dirName("");
373fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (language[0]) {
374fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        dirName += language;
375fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    } else {
376fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        return dirName;
377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
379fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (script[0]) {
380fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        dirName += "-s";
381fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        dirName += script;
382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
384fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (region[0]) {
385fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        dirName += "-r";
386fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        dirName += region;
387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
389fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (variant[0]) {
390fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        dirName += "-v";
391fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        dirName += variant;
392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
394fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    return dirName;
395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
397fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinskivoid AaptLocaleValue::initFromResTable(const ResTable_config& config) {
398fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    config.unpackLanguage(language);
399fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    config.unpackRegion(region);
400fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (config.localeScript[0]) {
401fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        memcpy(script, config.localeScript, sizeof(config.localeScript));
402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
404fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (config.localeVariant[0]) {
405fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        memcpy(variant, config.localeVariant, sizeof(config.localeVariant));
406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
409fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinskivoid AaptLocaleValue::writeTo(ResTable_config* out) const {
410fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    out->packLanguage(language);
411fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    out->packRegion(region);
412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
413fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (script[0]) {
414fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        memcpy(out->localeScript, script, sizeof(out->localeScript));
415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
417fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (variant[0]) {
418fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        memcpy(out->localeVariant, variant, sizeof(out->localeVariant));
419fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    }
420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
422fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinskibool
423fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam LesinskiAaptGroupEntry::initFromDirName(const char* dir, String8* resType)
424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
425fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    const char* q = strchr(dir, '-');
426fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    size_t typeLen;
427fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (q != NULL) {
428fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        typeLen = q - dir;
429fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    } else {
430fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        typeLen = strlen(dir);
431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
433fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    String8 type(dir, typeLen);
434fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (!isValidResourceType(type)) {
435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return false;
436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
437282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
438fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (q != NULL) {
439fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        if (!AaptConfig::parse(String8(q + 1), &mParams)) {
440fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            return false;
441fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        }
442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
444fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    *resType = type;
445282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return true;
446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
448fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam LesinskiString8
449fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam LesinskiAaptGroupEntry::toDirName(const String8& resType) const
450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
451fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    String8 s = resType;
452fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    String8 params = mParams.toString();
453fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (params.length() > 0) {
454fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        if (s.length() > 0) {
455fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            s += "-";
456fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        }
457fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        s += params;
458fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    }
459fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    return s;
460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =========================================================================
464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =========================================================================
465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =========================================================================
466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid* AaptFile::editData(size_t size)
468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (size <= mBufferSize) {
470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mDataSize = size;
471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return mData;
472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t allocSize = (size*3)/2;
474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    void* buf = realloc(mData, allocSize);
475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (buf == NULL) {
476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NULL;
477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mData = buf;
479282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mDataSize = size;
480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mBufferSize = allocSize;
481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return buf;
482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
484de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinskivoid* AaptFile::editDataInRange(size_t offset, size_t size)
485de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski{
486de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski    return (void*)(((uint8_t*) editData(offset + size)) + offset);
487de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski}
488de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski
489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid* AaptFile::editData(size_t* outSize)
490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (outSize) {
492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        *outSize = mDataSize;
493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return mData;
495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid* AaptFile::padData(size_t wordSize)
498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t extra = mDataSize%wordSize;
500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (extra == 0) {
501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return mData;
502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
504282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t initial = mDataSize;
505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    void* data = editData(initial+(wordSize-extra));
506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (data != NULL) {
507282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        memset(((uint8_t*)data) + initial, 0, wordSize-extra);
508282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
509282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return data;
510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
511282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
512282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t AaptFile::writeData(const void* data, size_t size)
513282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
514282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t end = mDataSize;
515282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t total = size + end;
516282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    void* buf = editData(total);
517282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (buf == NULL) {
518282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
519282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
520282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    memcpy(((char*)buf)+end, data, size);
521282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
522282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
523282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
524282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid AaptFile::clearData()
525282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
526282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mData != NULL) free(mData);
527282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mData = NULL;
528282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mDataSize = 0;
529282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mBufferSize = 0;
530282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
531282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
532282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiString8 AaptFile::getPrintableSource() const
533282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
534282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (hasData()) {
535282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String8 name(mGroupEntry.toDirName(String8()));
536282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        name.appendPath(mPath);
537282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        name.append(" #generated");
538282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return name;
539282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
540282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return mSourceFile;
541282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
542282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
543282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =========================================================================
544282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =========================================================================
545282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =========================================================================
546282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
54709384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinskistatus_t AaptGroup::addFile(const sp<AaptFile>& file, const bool overwriteDuplicate)
548282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
54909384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski    ssize_t index = mFiles.indexOfKey(file->getGroupEntry());
55009384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski    if (index >= 0 && overwriteDuplicate) {
55109384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski        fprintf(stderr, "warning: overwriting '%s' with '%s'\n",
55209384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski                mFiles[index]->getSourceFile().string(),
55309384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski                file->getSourceFile().string());
55409384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski        removeFile(index);
55509384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski        index = -1;
55609384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski    }
55709384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski
55809384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski    if (index < 0) {
559282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        file->mPath = mPath;
560282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mFiles.add(file->getGroupEntry(), file);
561282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NO_ERROR;
562282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
563282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
56448f05d29f398576c76b2c3b47a22f4e44e8919fcAdam Lesinski    // Check if the version is automatically applied. This is a common source of
56548f05d29f398576c76b2c3b47a22f4e44e8919fcAdam Lesinski    // error.
56648f05d29f398576c76b2c3b47a22f4e44e8919fcAdam Lesinski    ConfigDescription withoutVersion = file->getGroupEntry().toParams();
56748f05d29f398576c76b2c3b47a22f4e44e8919fcAdam Lesinski    withoutVersion.version = 0;
56848f05d29f398576c76b2c3b47a22f4e44e8919fcAdam Lesinski    AaptConfig::applyVersionForCompatibility(&withoutVersion);
56948f05d29f398576c76b2c3b47a22f4e44e8919fcAdam Lesinski
57048f05d29f398576c76b2c3b47a22f4e44e8919fcAdam Lesinski    const sp<AaptFile>& originalFile = mFiles.valueAt(index);
57148f05d29f398576c76b2c3b47a22f4e44e8919fcAdam Lesinski    SourcePos(file->getSourceFile(), -1)
57248f05d29f398576c76b2c3b47a22f4e44e8919fcAdam Lesinski            .error("Duplicate file.\n%s: Original is here. %s",
57348f05d29f398576c76b2c3b47a22f4e44e8919fcAdam Lesinski                   originalFile->getPrintableSource().string(),
57448f05d29f398576c76b2c3b47a22f4e44e8919fcAdam Lesinski                   (withoutVersion.version != 0) ? "The version qualifier may be implied." : "");
575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return UNKNOWN_ERROR;
576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid AaptGroup::removeFile(size_t index)
579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski	mFiles.removeItemsAt(index);
581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid AaptGroup::print(const String8& prefix) const
584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    printf("%s%s\n", prefix.string(), getPath().string());
586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t N=mFiles.size();
587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t i;
588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (i=0; i<N; i++) {
589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<AaptFile> file = mFiles.valueAt(i);
590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const AaptGroupEntry& e = file->getGroupEntry();
591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (file->hasData()) {
592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("%s  Gen: (%s) %d bytes\n", prefix.string(), e.toDirName(String8()).string(),
593282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    (int)file->getSize());
594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("%s  Src: (%s) %s\n", prefix.string(), e.toDirName(String8()).string(),
596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    file->getPrintableSource().string());
597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //printf("%s  File Group Entry: %s\n", prefix.string(),
599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //        file->getGroupEntry().toDirName(String8()).string());
600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
603282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiString8 AaptGroup::getPrintableSource() const
604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mFiles.size() > 0) {
606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Arbitrarily pull the first source file out of the list.
607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return mFiles.valueAt(0)->getPrintableSource();
608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Should never hit this case, but to be safe...
611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return getPath();
612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =========================================================================
616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =========================================================================
617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =========================================================================
618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t AaptDir::addFile(const String8& name, const sp<AaptGroup>& file)
620282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mFiles.indexOfKey(name) >= 0) {
622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return ALREADY_EXISTS;
623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mFiles.add(name, file);
625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
626282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
627282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
628282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t AaptDir::addDir(const String8& name, const sp<AaptDir>& dir)
629282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
630282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mDirs.indexOfKey(name) >= 0) {
631282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return ALREADY_EXISTS;
632282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
633282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mDirs.add(name, dir);
634282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
637282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisp<AaptDir> AaptDir::makeDir(const String8& path)
638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String8 name;
640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String8 remain = path;
641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<AaptDir> subdir = this;
643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (name = remain.walkPath(&remain), remain != "") {
644282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        subdir = subdir->makeDir(name);
645282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t i = subdir->mDirs.indexOfKey(name);
648282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (i >= 0) {
649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return subdir->mDirs.valueAt(i);
650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<AaptDir> dir = new AaptDir(name, subdir->mPath.appendPathCopy(name));
652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    subdir->mDirs.add(name, dir);
653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return dir;
654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid AaptDir::removeFile(const String8& name)
657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mFiles.removeItem(name);
659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid AaptDir::removeDir(const String8& name)
662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mDirs.removeItem(name);
664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
66609384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinskistatus_t AaptDir::addLeafFile(const String8& leafName, const sp<AaptFile>& file,
66709384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski        const bool overwrite)
668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<AaptGroup> group;
670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mFiles.indexOfKey(leafName) >= 0) {
671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        group = mFiles.valueFor(leafName);
672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        group = new AaptGroup(leafName, mPath.appendPathCopy(leafName));
674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mFiles.add(leafName, group);
675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
676282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
67709384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski    return group->addFile(file, overwrite);
678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
679282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
680282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskissize_t AaptDir::slurpFullTree(Bundle* bundle, const String8& srcDir,
681282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            const AaptGroupEntry& kind, const String8& resType,
68209384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski                            sp<FilePathStore>& fullResPaths, const bool overwrite)
683282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
684282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Vector<String8> fileNames;
685282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    {
686282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        DIR* dir = NULL;
687282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dir = opendir(srcDir.string());
689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (dir == NULL) {
690282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: opendir(%s): %s\n", srcDir.string(), strerror(errno));
691282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return UNKNOWN_ERROR;
692282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
693282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
694282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        /*
695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         * Slurp the filenames out of the directory.
696282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         */
697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        while (1) {
698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            struct dirent* entry;
699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
700282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            entry = readdir(dir);
701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (entry == NULL)
702282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                break;
703282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
704282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (isHidden(srcDir.string(), entry->d_name))
705282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
706282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
707282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 name(entry->d_name);
708282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fileNames.add(name);
709282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Add fully qualified path for dependency purposes
710282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // if we're collecting them
711282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (fullResPaths != NULL) {
712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fullResPaths->add(srcDir.appendPathCopy(name));
713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
714282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        closedir(dir);
716282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
717282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
718282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t count = 0;
719282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
720282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*
721282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Stash away the files and recursively descend into subdirectories.
722282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
723282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t N = fileNames.size();
724282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t i;
725282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (i = 0; i < N; i++) {
726282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String8 pathName(srcDir);
727282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        FileType type;
728282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
729282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        pathName.appendPath(fileNames[i].string());
730282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        type = getFileType(pathName.string());
731282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (type == kFileTypeDirectory) {
732282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<AaptDir> subdir;
733282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool notAdded = false;
734282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (mDirs.indexOfKey(fileNames[i]) >= 0) {
735282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                subdir = mDirs.valueFor(fileNames[i]);
736282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
737282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                subdir = new AaptDir(fileNames[i], mPath.appendPathCopy(fileNames[i]));
738282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                notAdded = true;
739282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
740282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ssize_t res = subdir->slurpFullTree(bundle, pathName, kind,
74109384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski                                                resType, fullResPaths, overwrite);
742282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (res < NO_ERROR) {
743282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return res;
744282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
745282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (res > 0 && notAdded) {
746282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                mDirs.add(fileNames[i], subdir);
747282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
748282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            count += res;
749282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else if (type == kFileTypeRegular) {
750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<AaptFile> file = new AaptFile(pathName, kind, resType);
75109384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski            status_t err = addLeafFile(fileNames[i], file, overwrite);
752282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (err != NO_ERROR) {
753282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return err;
754282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
755282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
756282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            count++;
757282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
758282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
759282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (bundle->getVerbose())
760282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("   (ignoring non-file/dir '%s')\n", pathName.string());
761282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
762282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
763282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
764282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return count;
765282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
766282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
767282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t AaptDir::validate() const
768282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
769282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t NF = mFiles.size();
770282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t ND = mDirs.size();
771282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t i;
772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (i = 0; i < NF; i++) {
773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!validateFileName(mFiles.valueAt(i)->getLeaf().string())) {
774282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            SourcePos(mFiles.valueAt(i)->getPrintableSource(), -1).error(
775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    "Invalid filename.  Unable to add.");
776282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return UNKNOWN_ERROR;
777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        size_t j;
780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (j = i+1; j < NF; j++) {
781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (strcasecmp(mFiles.valueAt(i)->getLeaf().string(),
782282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           mFiles.valueAt(j)->getLeaf().string()) == 0) {
783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos(mFiles.valueAt(i)->getPrintableSource(), -1).error(
784282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "File is case-insensitive equivalent to: %s",
785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        mFiles.valueAt(j)->getPrintableSource().string());
786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return UNKNOWN_ERROR;
787282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
788282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
789282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // TODO: if ".gz", check for non-.gz; if non-, check for ".gz"
790282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // (this is mostly caught by the "marked" stuff, below)
791282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
792282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
793282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (j = 0; j < ND; j++) {
794282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (strcasecmp(mFiles.valueAt(i)->getLeaf().string(),
795282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           mDirs.valueAt(j)->getLeaf().string()) == 0) {
796282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos(mFiles.valueAt(i)->getPrintableSource(), -1).error(
797282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "File conflicts with dir from: %s",
798282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        mDirs.valueAt(j)->getPrintableSource().string());
799282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return UNKNOWN_ERROR;
800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
801282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
802282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
803282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
804282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (i = 0; i < ND; i++) {
805282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!validateFileName(mDirs.valueAt(i)->getLeaf().string())) {
806282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            SourcePos(mDirs.valueAt(i)->getPrintableSource(), -1).error(
807282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    "Invalid directory name, unable to add.");
808282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return UNKNOWN_ERROR;
809282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
810282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
811282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        size_t j;
812282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (j = i+1; j < ND; j++) {
813282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (strcasecmp(mDirs.valueAt(i)->getLeaf().string(),
814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           mDirs.valueAt(j)->getLeaf().string()) == 0) {
815282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos(mDirs.valueAt(i)->getPrintableSource(), -1).error(
816282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "Directory is case-insensitive equivalent to: %s",
817282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        mDirs.valueAt(j)->getPrintableSource().string());
818282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return UNKNOWN_ERROR;
819282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
820282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
821282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
822282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        status_t err = mDirs.valueAt(i)->validate();
823282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != NO_ERROR) {
824282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return err;
825282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
826282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
827282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
828282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
829282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
830282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
831282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid AaptDir::print(const String8& prefix) const
832282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
833282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t ND=getDirs().size();
834282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t i;
835282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (i=0; i<ND; i++) {
836282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        getDirs().valueAt(i)->print(prefix);
837282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
838282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
839282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t NF=getFiles().size();
840282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (i=0; i<NF; i++) {
841282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        getFiles().valueAt(i)->print(prefix);
842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
843282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
844282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
845282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiString8 AaptDir::getPrintableSource() const
846282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
847282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mFiles.size() > 0) {
848282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Arbitrarily pull the first file out of the list as the source dir.
849282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return mFiles.valueAt(0)->getPrintableSource().getPathDir();
850282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
851282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mDirs.size() > 0) {
852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Or arbitrarily pull the first dir out of the list as the source dir.
853282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return mDirs.valueAt(0)->getPrintableSource().getPathDir();
854282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
855282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
856282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Should never hit this case, but to be safe...
857282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return mPath;
858282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
859282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
860282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
861282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =========================================================================
862282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =========================================================================
863282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =========================================================================
864282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
865282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t AaptSymbols::applyJavaSymbols(const sp<AaptSymbols>& javaSymbols)
866282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
867282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = NO_ERROR;
868282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t N = javaSymbols->mSymbols.size();
869282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (size_t i=0; i<N; i++) {
870282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String8& name = javaSymbols->mSymbols.keyAt(i);
871282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const AaptSymbolEntry& entry = javaSymbols->mSymbols.valueAt(i);
872282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ssize_t pos = mSymbols.indexOfKey(name);
873282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (pos < 0) {
874282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            entry.sourcePos.error("Symbol '%s' declared with <java-symbol> not defined\n", name.string());
875282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            err = UNKNOWN_ERROR;
876282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
877282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
878282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //printf("**** setting symbol #%d/%d %s to isJavaSymbol=%d\n",
879282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //        i, N, name.string(), entry.isJavaSymbol ? 1 : 0);
880282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mSymbols.editValueAt(pos).isJavaSymbol = entry.isJavaSymbol;
881282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
882282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
883282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    N = javaSymbols->mNestedSymbols.size();
884282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (size_t i=0; i<N; i++) {
885282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String8& name = javaSymbols->mNestedSymbols.keyAt(i);
886282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const sp<AaptSymbols>& symbols = javaSymbols->mNestedSymbols.valueAt(i);
887282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ssize_t pos = mNestedSymbols.indexOfKey(name);
888282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (pos < 0) {
889282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            SourcePos pos;
890282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            pos.error("Java symbol dir %s not defined\n", name.string());
891282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            err = UNKNOWN_ERROR;
892282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
893282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
894282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //printf("**** applying java symbols in dir %s\n", name.string());
895282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        status_t myerr = mNestedSymbols.valueAt(pos)->applyJavaSymbols(symbols);
896282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (myerr != NO_ERROR) {
897282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            err = myerr;
898282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
899282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
900282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
901282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return err;
902282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
903282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
904282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =========================================================================
905282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =========================================================================
906282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =========================================================================
907282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
908282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiAaptAssets::AaptAssets()
909282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    : AaptDir(String8(), String8()),
91091447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath      mHavePrivateSymbols(false),
91191447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath      mChanged(false), mHaveIncludedAssets(false),
912fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski      mRes(NULL) {}
913282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
914282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiconst SortedVector<AaptGroupEntry>& AaptAssets::getGroupEntries() const {
915282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mChanged) {
916282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
917282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return mGroupEntries;
918282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
919282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
920282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t AaptAssets::addFile(const String8& name, const sp<AaptGroup>& file)
921282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
922282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mChanged = true;
923282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return AaptDir::addFile(name, file);
924282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
925282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
926282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisp<AaptFile> AaptAssets::addFile(
927282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String8& filePath, const AaptGroupEntry& entry,
928282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String8& srcDir, sp<AaptGroup>* outGroup,
929282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String8& resType)
930282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
931282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<AaptDir> dir = this;
932282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<AaptGroup> group;
933282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<AaptFile> file;
934282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String8 root, remain(filePath), partialPath;
935282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (remain.length() > 0) {
936282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        root = remain.walkPath(&remain);
937282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        partialPath.appendPath(root);
938282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
939282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String8 rootStr(root);
940282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
941282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (remain.length() == 0) {
942282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ssize_t i = dir->getFiles().indexOfKey(rootStr);
943282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (i >= 0) {
944282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                group = dir->getFiles().valueAt(i);
945282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
946282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                group = new AaptGroup(rootStr, filePath);
947282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                status_t res = dir->addFile(rootStr, group);
948282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (res != NO_ERROR) {
949282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return NULL;
950282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
951282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
952282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            file = new AaptFile(srcDir.appendPathCopy(filePath), entry, resType);
953282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            status_t res = group->addFile(file);
954282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (res != NO_ERROR) {
955282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return NULL;
956282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
957282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            break;
958282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
959282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
960282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ssize_t i = dir->getDirs().indexOfKey(rootStr);
961282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (i >= 0) {
962282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                dir = dir->getDirs().valueAt(i);
963282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
964282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<AaptDir> subdir = new AaptDir(rootStr, partialPath);
965282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                status_t res = dir->addDir(rootStr, subdir);
966282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (res != NO_ERROR) {
967282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return NULL;
968282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
969282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                dir = subdir;
970282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
971282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
972282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
973282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
974282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mGroupEntries.add(entry);
975282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (outGroup) *outGroup = group;
976282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return file;
977282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
978282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
979282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid AaptAssets::addResource(const String8& leafName, const String8& path,
980282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                const sp<AaptFile>& file, const String8& resType)
981282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
982282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<AaptDir> res = AaptDir::makeDir(kResString);
983282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String8 dirname = file->getGroupEntry().toDirName(resType);
984282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<AaptDir> subdir = res->makeDir(dirname);
985282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<AaptGroup> grr = new AaptGroup(leafName, path);
986282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    grr->addFile(file);
987282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
988282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    subdir->addFile(leafName, grr);
989282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
990282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
991282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
992282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskissize_t AaptAssets::slurpFromArgs(Bundle* bundle)
993282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
994282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int count;
995282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int totalCount = 0;
996282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    FileType type;
997282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const Vector<const char *>& resDirs = bundle->getResourceSourceDirs();
998282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t dirCount =resDirs.size();
999282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<AaptAssets> current = this;
1000282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1001282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const int N = bundle->getFileSpecCount();
1002282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1003282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*
1004282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * If a package manifest was specified, include that first.
1005282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
1006282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getAndroidManifestFile() != NULL) {
1007282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // place at root of zip.
1008282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String8 srcFile(bundle->getAndroidManifestFile());
1009282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        addFile(srcFile.getPathLeaf(), AaptGroupEntry(), srcFile.getPathDir(),
1010282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                NULL, String8());
1011282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        totalCount++;
1012282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1013282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1014282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*
1015282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * If a directory of custom assets was supplied, slurp 'em up.
1016282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
101709384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski    const Vector<const char*>& assetDirs = bundle->getAssetSourceDirs();
101809384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski    const int AN = assetDirs.size();
101909384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski    for (int i = 0; i < AN; i++) {
102009384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski        FileType type = getFileType(assetDirs[i]);
1021282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (type == kFileTypeNonexistent) {
102209384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski            fprintf(stderr, "ERROR: asset directory '%s' does not exist\n", assetDirs[i]);
1023282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return UNKNOWN_ERROR;
1024282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1025282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (type != kFileTypeDirectory) {
102609384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski            fprintf(stderr, "ERROR: '%s' is not a directory\n", assetDirs[i]);
1027282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return UNKNOWN_ERROR;
1028282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1029282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
103009384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski        String8 assetRoot(assetDirs[i]);
1031282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<AaptDir> assetAaptDir = makeDir(String8(kAssetDir));
1032282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        AaptGroupEntry group;
1033282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        count = assetAaptDir->slurpFullTree(bundle, assetRoot, group,
103409384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski                                            String8(), mFullAssetPaths, true);
1035282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (count < 0) {
1036282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            totalCount = count;
1037282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
1038282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1039282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (count > 0) {
1040282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mGroupEntries.add(group);
1041282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1042282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        totalCount += count;
1043282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
104409384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski        if (bundle->getVerbose()) {
1045282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("Found %d custom asset file%s in %s\n",
104609384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski                   count, (count==1) ? "" : "s", assetDirs[i]);
104709384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski        }
1048282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1049282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1050282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*
1051282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * If a directory of resource-specific assets was supplied, slurp 'em up.
1052282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
1053282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (size_t i=0; i<dirCount; i++) {
1054282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const char *res = resDirs[i];
1055282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (res) {
1056282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            type = getFileType(res);
1057282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (type == kFileTypeNonexistent) {
1058282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, "ERROR: resource directory '%s' does not exist\n", res);
1059282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return UNKNOWN_ERROR;
1060282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1061282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (type == kFileTypeDirectory) {
1062282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (i>0) {
1063282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sp<AaptAssets> nextOverlay = new AaptAssets();
1064282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    current->setOverlay(nextOverlay);
1065282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    current = nextOverlay;
1066282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    current->setFullResPaths(mFullResPaths);
1067282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1068282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                count = current->slurpResourceTree(bundle, String8(res));
10699ab9b93eae8b2fc747d6101cf0e4c19b2218715fBryan Mawhinney                if (i > 0 && count > 0) {
10709ab9b93eae8b2fc747d6101cf0e4c19b2218715fBryan Mawhinney                  count = current->filter(bundle);
10719ab9b93eae8b2fc747d6101cf0e4c19b2218715fBryan Mawhinney                }
1072282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1073282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (count < 0) {
1074282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    totalCount = count;
1075282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    goto bail;
1076282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1077282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                totalCount += count;
1078282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1079282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            else {
1080282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, "ERROR: '%s' is not a directory\n", res);
1081282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return UNKNOWN_ERROR;
1082282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1083282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1084282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1085282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1086282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*
1087282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Now do any additional raw files.
1088282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
1089282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (int arg=0; arg<N; arg++) {
1090282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const char* assetDir = bundle->getFileSpecEntry(arg);
1091282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1092282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        FileType type = getFileType(assetDir);
1093282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (type == kFileTypeNonexistent) {
1094282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: input directory '%s' does not exist\n", assetDir);
1095282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return UNKNOWN_ERROR;
1096282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1097282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (type != kFileTypeDirectory) {
1098282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: '%s' is not a directory\n", assetDir);
1099282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return UNKNOWN_ERROR;
1100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String8 assetRoot(assetDir);
1103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (bundle->getVerbose())
1105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("Processing raw dir '%s'\n", (const char*) assetDir);
1106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        /*
1108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         * Do a recursive traversal of subdir tree.  We don't make any
1109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         * guarantees about ordering, so we're okay with an inorder search
1110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         * using whatever order the OS happens to hand back to us.
1111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         */
1112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        count = slurpFullTree(bundle, assetRoot, AaptGroupEntry(), String8(), mFullAssetPaths);
1113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (count < 0) {
1114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            /* failure; report error and remove archive */
1115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            totalCount = count;
1116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
1117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        totalCount += count;
1119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (bundle->getVerbose())
1121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("Found %d asset file%s in %s\n",
1122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                   count, (count==1) ? "" : "s", assetDir);
1123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    count = validate();
1126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (count != NO_ERROR) {
1127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        totalCount = count;
1128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
1129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    count = filter(bundle);
1132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (count != NO_ERROR) {
1133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        totalCount = count;
1134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
1135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail:
1138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return totalCount;
1139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskissize_t AaptAssets::slurpFullTree(Bundle* bundle, const String8& srcDir,
1142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    const AaptGroupEntry& kind,
1143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    const String8& resType,
114440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                                    sp<FilePathStore>& fullResPaths,
114540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                                    const bool overwrite)
1146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
114740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    ssize_t res = AaptDir::slurpFullTree(bundle, srcDir, kind, resType, fullResPaths, overwrite);
1148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (res > 0) {
1149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mGroupEntries.add(kind);
1150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return res;
1153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskissize_t AaptAssets::slurpResourceTree(Bundle* bundle, const String8& srcDir)
1156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t err = 0;
1158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    DIR* dir = opendir(srcDir.string());
1160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (dir == NULL) {
1161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: opendir(%s): %s\n", srcDir.string(), strerror(errno));
1162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
1163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t count = 0;
1166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*
1168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Run through the directory, looking for dirs that match the
1169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * expected pattern.
1170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
1171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (1) {
1172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        struct dirent* entry = readdir(dir);
1173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (entry == NULL) {
1174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            break;
1175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (isHidden(srcDir.string(), entry->d_name)) {
1178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
1179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String8 subdirName(srcDir);
1182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        subdirName.appendPath(entry->d_name);
1183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        AaptGroupEntry group;
1185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String8 resType;
1186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        bool b = group.initFromDirName(entry->d_name, &resType);
1187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!b) {
1188fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            fprintf(stderr, "invalid resource directory name: %s %s\n", srcDir.string(),
1189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    entry->d_name);
1190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            err = -1;
1191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
1192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (bundle->getMaxResVersion() != NULL && group.getVersionString().length() != 0) {
1195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int maxResInt = atoi(bundle->getMaxResVersion());
1196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const char *verString = group.getVersionString().string();
1197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int dirVersionInt = atoi(verString + 1); // skip 'v' in version name
1198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (dirVersionInt > maxResInt) {
1199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski              fprintf(stderr, "max res %d, skipping %s\n", maxResInt, entry->d_name);
1200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski              continue;
1201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        FileType type = getFileType(subdirName.string());
1205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (type == kFileTypeDirectory) {
1207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<AaptDir> dir = makeDir(resType);
1208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ssize_t res = dir->slurpFullTree(bundle, subdirName, group,
1209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                resType, mFullResPaths);
1210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (res < 0) {
1211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                count = res;
1212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                goto bail;
1213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (res > 0) {
1215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                mGroupEntries.add(group);
1216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                count += res;
1217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Only add this directory if we don't already have a resource dir
1220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // for the current type.  This ensures that we only add the dir once
1221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // for all configs.
1222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<AaptDir> rdir = resDir(resType);
1223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (rdir == NULL) {
1224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                mResDirs.add(dir);
1225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
1227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (bundle->getVerbose()) {
1228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, "   (ignoring file '%s')\n", subdirName.string());
1229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail:
1234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    closedir(dir);
1235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    dir = NULL;
1236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != 0) {
1238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return err;
1239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return count;
1241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskissize_t
1244282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiAaptAssets::slurpResourceZip(Bundle* bundle, const char* filename)
1245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int count = 0;
1247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    SortedVector<AaptGroupEntry> entries;
1248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ZipFile* zip = new ZipFile;
1250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = zip->open(filename, ZipFile::kOpenReadOnly);
1251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
1252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "error opening zip file %s\n", filename);
1253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        count = err;
1254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        delete zip;
1255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return -1;
1256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const int N = zip->getNumEntries();
1259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (int i=0; i<N; i++) {
1260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ZipEntry* entry = zip->getEntryByIndex(i);
1261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (entry->getDeleted()) {
1262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
1263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String8 entryName(entry->getFileName());
1266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String8 dirName = entryName.getPathDir();
1268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<AaptDir> dir = dirName == "" ? this : makeDir(dirName);
1269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String8 resType;
1271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        AaptGroupEntry kind;
1272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String8 remain;
1274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (entryName.walkPath(&remain) == kResourceDir) {
1275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // these are the resources, pull their type out of the directory name
1276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            kind.initFromDirName(remain.walkPath().string(), &resType);
1277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
1278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // these are untyped and don't have an AaptGroupEntry
1279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (entries.indexOf(kind) < 0) {
1281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            entries.add(kind);
1282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mGroupEntries.add(kind);
1283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // use the one from the zip file if they both exist.
1286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dir->removeFile(entryName.getPathLeaf());
1287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<AaptFile> file = new AaptFile(entryName, kind, resType);
1289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        status_t err = dir->addLeafFile(entryName.getPathLeaf(), file);
1290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != NO_ERROR) {
1291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "err=%s entryName=%s\n", strerror(err), entryName.string());
1292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            count = err;
1293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
1294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        file->setCompressionMethod(entry->getCompressionMethod());
1296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#if 0
1298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (entryName == "AndroidManifest.xml") {
1299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("AndroidManifest.xml\n");
1300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printf("\n\nfile: %s\n", entryName.string());
1302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif
1303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        size_t len = entry->getUncompressedLen();
1305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        void* data = zip->uncompress(entry);
1306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        void* buf = file->editData(len);
1307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        memcpy(buf, data, len);
1308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#if 0
1310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const int OFF = 0;
1311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const unsigned char* p = (unsigned char*)data;
1312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const unsigned char* end = p+len;
1313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        p += OFF;
1314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (int i=0; i<32 && p < end; i++) {
1315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("0x%03x ", i*0x10 + OFF);
1316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (int j=0; j<0x10 && p < end; j++) {
1317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf(" %02x", *p);
1318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                p++;
1319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("\n");
1321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif
1323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        free(data);
1325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        count++;
1327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail:
1330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    delete zip;
1331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return count;
1332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t AaptAssets::filter(Bundle* bundle)
1335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1336fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    WeakResourceFilter reqFilter;
1337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = reqFilter.parse(bundle->getConfigurations());
1338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
1339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return err;
1340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1342fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    uint32_t preferredDensity = 0;
1343fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (bundle->getPreferredDensity().size() > 0) {
1344fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        ResTable_config preferredConfig;
1345fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        if (!AaptConfig::parseDensity(bundle->getPreferredDensity().string(), &preferredConfig)) {
1346fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            fprintf(stderr, "Error parsing preferred density: %s\n",
1347fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    bundle->getPreferredDensity().string());
1348fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            return UNKNOWN_ERROR;
1349fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        }
1350fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        preferredDensity = preferredConfig.density;
1351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1353fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (reqFilter.isEmpty() && preferredDensity == 0) {
1354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NO_ERROR;
1355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getVerbose()) {
1358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!reqFilter.isEmpty()) {
1359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("Applying required filter: %s\n",
1360fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    bundle->getConfigurations().string());
1361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1362fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        if (preferredDensity > 0) {
1363fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            printf("Applying preferred density filter: %s\n",
1364fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    bundle->getPreferredDensity().string());
1365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const Vector<sp<AaptDir> >& resdirs = mResDirs;
1369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t ND = resdirs.size();
1370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (size_t i=0; i<ND; i++) {
1371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const sp<AaptDir>& dir = resdirs.itemAt(i);
1372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (dir->getLeaf() == kValuesDir) {
1373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // The "value" dir is special since a single file defines
1374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // multiple resources, so we can not do filtering on the
1375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // files themselves.
1376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
1377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (dir->getLeaf() == kMipmapDir) {
1379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // We also skip the "mipmap" directory, since the point of this
1380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // is to include all densities without stripping.  If you put
1381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // other configurations in here as well they won't be stripped
1382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // either...  So don't do that.  Seriously.  What is wrong with you?
1383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
1384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t NG = dir->getFiles().size();
1387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (size_t j=0; j<NG; j++) {
1388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<AaptGroup> grp = dir->getFiles().valueAt(j);
1389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // First remove any configurations we know we don't need.
1391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t k=0; k<grp->getFiles().size(); k++) {
1392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<AaptFile> file = grp->getFiles().valueAt(k);
1393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (k == 0 && grp->getFiles().size() == 1) {
1394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // If this is the only file left, we need to keep it.
1395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // Otherwise the resource IDs we are using will be inconsistent
1396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // with what we get when not stripping.  Sucky, but at least
1397282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // for now we can rely on the back-end doing another filtering
1398282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // pass to take this out and leave us with this resource name
1399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // containing no entries.
1400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
1401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (file->getPath().getPathExtension() == ".xml") {
1403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // We can't remove .xml files at this point, because when
1404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // we parse them they may add identifier resources, so
1405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // removing them can cause our resource identifiers to
1406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // become inconsistent.
1407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
1408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                const ResTable_config& config(file->getGroupEntry().toParams());
1410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!reqFilter.match(config)) {
1411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (bundle->getVerbose()) {
1412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        printf("Pruning unneeded resource: %s\n",
1413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                file->getPrintableSource().string());
1414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    grp->removeFile(k);
1416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    k--;
1417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Quick check: no preferred filters, nothing more to do.
1421fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            if (preferredDensity == 0) {
1422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
1423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
14258cf61845187e301dfc4f64b42921977d38766a34Adam Lesinski            // Get the preferred density if there is one. We do not match exactly for density.
14268cf61845187e301dfc4f64b42921977d38766a34Adam Lesinski            // If our preferred density is hdpi but we only have mdpi and xhdpi resources, we
14278cf61845187e301dfc4f64b42921977d38766a34Adam Lesinski            // pick xhdpi.
1428fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            for (size_t k=0; k<grp->getFiles().size(); k++) {
1429fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                sp<AaptFile> file = grp->getFiles().valueAt(k);
1430fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                if (k == 0 && grp->getFiles().size() == 1) {
1431fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    // If this is the only file left, we need to keep it.
1432fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    // Otherwise the resource IDs we are using will be inconsistent
1433fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    // with what we get when not stripping.  Sucky, but at least
1434fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    // for now we can rely on the back-end doing another filtering
1435fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    // pass to take this out and leave us with this resource name
1436fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    // containing no entries.
1437fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    continue;
1438fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                }
1439fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                if (file->getPath().getPathExtension() == ".xml") {
1440fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    // We can't remove .xml files at this point, because when
1441fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    // we parse them they may add identifier resources, so
1442fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    // removing them can cause our resource identifiers to
1443fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    // become inconsistent.
1444fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    continue;
1445fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                }
1446fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                const ResTable_config& config(file->getGroupEntry().toParams());
1447fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                if (config.density != 0 && config.density != preferredDensity) {
1448fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    // This is a resource we would prefer not to have.  Check
1449fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    // to see if have a similar variation that we would like
1450fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    // to have and, if so, we can drop it.
1451fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    uint32_t bestDensity = config.density;
1452fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski
1453fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    for (size_t m=0; m<grp->getFiles().size(); m++) {
1454fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                        if (m == k) {
1455fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                            continue;
1456fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                        }
14578cf61845187e301dfc4f64b42921977d38766a34Adam Lesinski
1458fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                        sp<AaptFile> mfile = grp->getFiles().valueAt(m);
1459fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                        const ResTable_config& mconfig(mfile->getGroupEntry().toParams());
1460fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                        if (AaptConfig::isSameExcept(config, mconfig, ResTable_config::CONFIG_DENSITY)) {
1461fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                            // See if there is a better density resource
1462fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                            if (mconfig.density < bestDensity &&
1463b0db8de73e6e4151b4e9d1fe3be1f609c3c1fb83Bryan Mawhinney                                    mconfig.density >= preferredDensity &&
1464fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                                    bestDensity > preferredDensity) {
1465b0db8de73e6e4151b4e9d1fe3be1f609c3c1fb83Bryan Mawhinney                                // This density is our preferred density, or between our best density and
1466fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                                // the preferred density, therefore it is better.
1467fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                                bestDensity = mconfig.density;
1468fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                            } else if (mconfig.density > bestDensity &&
1469fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                                    bestDensity < preferredDensity) {
1470fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                                // This density is better than our best density and
1471fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                                // our best density was smaller than our preferred
1472fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                                // density, so it is better.
1473fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                                bestDensity = mconfig.density;
1474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1476fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    }
14778cf61845187e301dfc4f64b42921977d38766a34Adam Lesinski
1478fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    if (bestDensity != config.density) {
1479fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                        if (bundle->getVerbose()) {
1480fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                            printf("Pruning unneeded resource: %s\n",
1481fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                                    file->getPrintableSource().string());
14828cf61845187e301dfc4f64b42921977d38766a34Adam Lesinski                        }
1483fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                        grp->removeFile(k);
1484fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                        k--;
1485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
1492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisp<AaptSymbols> AaptAssets::getSymbolsFor(const String8& name)
1495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<AaptSymbols> sym = mSymbols.valueFor(name);
1497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (sym == NULL) {
1498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sym = new AaptSymbols();
1499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mSymbols.add(name, sym);
1500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return sym;
1502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1504282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisp<AaptSymbols> AaptAssets::getJavaSymbolsFor(const String8& name)
1505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<AaptSymbols> sym = mJavaSymbols.valueFor(name);
1507282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (sym == NULL) {
1508282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sym = new AaptSymbols();
1509282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mJavaSymbols.add(name, sym);
1510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1511282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return sym;
1512282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1513282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1514282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t AaptAssets::applyJavaSymbols()
1515282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1516282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t N = mJavaSymbols.size();
1517282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (size_t i=0; i<N; i++) {
1518282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String8& name = mJavaSymbols.keyAt(i);
1519282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const sp<AaptSymbols>& symbols = mJavaSymbols.valueAt(i);
1520282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ssize_t pos = mSymbols.indexOfKey(name);
1521282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (pos < 0) {
1522282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            SourcePos pos;
1523282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            pos.error("Java symbol dir %s not defined\n", name.string());
1524282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return UNKNOWN_ERROR;
1525282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1526282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //printf("**** applying java symbols in dir %s\n", name.string());
1527282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        status_t err = mSymbols.valueAt(pos)->applyJavaSymbols(symbols);
1528282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != NO_ERROR) {
1529282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return err;
1530282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1531282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1532282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1533282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
1534282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1535282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1536282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool AaptAssets::isJavaSymbol(const AaptSymbolEntry& sym, bool includePrivate) const {
1537282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //printf("isJavaSymbol %s: public=%d, includePrivate=%d, isJavaSymbol=%d\n",
1538282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //        sym.name.string(), sym.isPublic ? 1 : 0, includePrivate ? 1 : 0,
1539282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //        sym.isJavaSymbol ? 1 : 0);
1540282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (!mHavePrivateSymbols) return true;
1541282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (sym.isPublic) return true;
1542282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (includePrivate && sym.isJavaSymbol) return true;
1543282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
1544282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1545282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1546282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t AaptAssets::buildIncludedResources(Bundle* bundle)
1547282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1548833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    if (mHaveIncludedAssets) {
1549833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        return NO_ERROR;
1550833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    }
1551833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski
1552833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    // Add in all includes.
1553833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    const Vector<String8>& includes = bundle->getPackageIncludes();
1554833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    const size_t packageIncludeCount = includes.size();
1555833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    for (size_t i = 0; i < packageIncludeCount; i++) {
1556833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        if (bundle->getVerbose()) {
1557833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            printf("Including resources from package: %s\n", includes[i].string());
1558833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        }
1559833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski
1560833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        if (!mIncludedAssets.addAssetPath(includes[i], NULL)) {
1561833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            fprintf(stderr, "ERROR: Asset package include '%s' not found.\n",
1562833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                    includes[i].string());
1563833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            return UNKNOWN_ERROR;
1564282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1565282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1566282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1567833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    const String8& featureOfBase = bundle->getFeatureOfPackage();
1568833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    if (!featureOfBase.isEmpty()) {
1569833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        if (bundle->getVerbose()) {
1570833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            printf("Including base feature resources from package: %s\n",
1571833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                    featureOfBase.string());
1572833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        }
1573833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski
1574833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        if (!mIncludedAssets.addAssetPath(featureOfBase, NULL)) {
1575833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            fprintf(stderr, "ERROR: base feature package '%s' not found.\n",
1576833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                    featureOfBase.string());
1577833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            return UNKNOWN_ERROR;
1578833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        }
1579833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    }
1580833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski
1581833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    mHaveIncludedAssets = true;
1582833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski
1583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
1584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t AaptAssets::addIncludedResources(const sp<AaptFile>& file)
1587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const ResTable& res = getIncludedResources();
1589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // XXX dirty!
159000b314436f4fdfada4bbf1e79ec12e9fa38aeaf1Narayan Kamath    return const_cast<ResTable&>(res).add(file->getData(), file->getSize());
1591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1593282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiconst ResTable& AaptAssets::getIncludedResources() const
1594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return mIncludedAssets.getResources(false);
1596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1598ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam LesinskiAssetManager& AaptAssets::getAssetManager()
1599ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski{
1600ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski    return mIncludedAssets;
1601ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski}
1602ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski
1603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid AaptAssets::print(const String8& prefix) const
1604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String8 innerPrefix(prefix);
1606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    innerPrefix.append("  ");
1607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String8 innerInnerPrefix(innerPrefix);
1608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    innerInnerPrefix.append("  ");
1609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    printf("%sConfigurations:\n", prefix.string());
1610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t N=mGroupEntries.size();
1611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (size_t i=0; i<N; i++) {
1612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String8 cname = mGroupEntries.itemAt(i).toDirName(String8());
1613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printf("%s %s\n", prefix.string(),
1614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                cname != "" ? cname.string() : "(default)");
1615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    printf("\n%sFiles:\n", prefix.string());
1618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    AaptDir::print(innerPrefix);
1619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1620282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    printf("\n%sResource Dirs:\n", prefix.string());
1621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const Vector<sp<AaptDir> >& resdirs = mResDirs;
1622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t NR = resdirs.size();
1623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (size_t i=0; i<NR; i++) {
1624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const sp<AaptDir>& d = resdirs.itemAt(i);
1625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printf("%s  Type %s\n", prefix.string(), d->getLeaf().string());
1626282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        d->print(innerInnerPrefix);
1627282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1628282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1629282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1630282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisp<AaptDir> AaptAssets::resDir(const String8& name) const
1631282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1632282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const Vector<sp<AaptDir> >& resdirs = mResDirs;
1633282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t N = resdirs.size();
1634282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (size_t i=0; i<N; i++) {
1635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const sp<AaptDir>& d = resdirs.itemAt(i);
1636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (d->getLeaf() == name) {
1637282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return d;
1638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NULL;
1641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool
1644282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivalid_symbol_name(const String8& symbol)
1645282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    static char const * const KEYWORDS[] = {
1647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        "abstract", "assert", "boolean", "break",
1648282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        "byte", "case", "catch", "char", "class", "const", "continue",
1649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        "default", "do", "double", "else", "enum", "extends", "final",
1650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        "finally", "float", "for", "goto", "if", "implements", "import",
1651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        "instanceof", "int", "interface", "long", "native", "new", "package",
1652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        "private", "protected", "public", "return", "short", "static",
1653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        "strictfp", "super", "switch", "synchronized", "this", "throw",
1654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        "throws", "transient", "try", "void", "volatile", "while",
1655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        "true", "false", "null",
1656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        NULL
1657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    };
1658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char*const* k = KEYWORDS;
1659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char*const s = symbol.string();
1660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (*k) {
1661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (0 == strcmp(s, *k)) {
1662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;
1663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        k++;
1665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return true;
1667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1668