Command.cpp revision ad2d07d2d98a46babb2a9472413fe9ce5080ca76
1282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//
2282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// Copyright 2006 The Android Open Source Project
3282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//
4282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// Android Asset Packaging Tool main entry point.
5282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//
6ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski#include "AaptXml.h"
7fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski#include "ApkBuilder.h"
8282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "Bundle.h"
92c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include "Images.h"
102c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include "Main.h"
11282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "ResourceFilter.h"
12282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "ResourceTable.h"
13282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "XMLNode.h"
14282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
152c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include <utils/Errors.h>
162c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include <utils/KeyedVector.h>
172c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include <utils/List.h>
18282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <utils/Log.h>
192c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include <utils/SortedVector.h>
20282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <utils/threads.h>
212c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include <utils/Vector.h>
22282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
23282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <errno.h>
242c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include <fcntl.h>
25282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
26282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiusing namespace android;
27282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
28ad751224401564dcc8338df3d5c4c5de7722be8fAdam Lesinski#ifndef AAPT_VERSION
29ad751224401564dcc8338df3d5c4c5de7722be8fAdam Lesinski    #define AAPT_VERSION ""
30ad751224401564dcc8338df3d5c4c5de7722be8fAdam Lesinski#endif
31ad751224401564dcc8338df3d5c4c5de7722be8fAdam Lesinski
32282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
33282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Show version info.  All the cool kids do it.
34282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
35282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doVersion(Bundle* bundle)
36282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
37282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getFileSpecCount() != 0) {
38282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printf("(ignoring extra arguments)\n");
39282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
40ad751224401564dcc8338df3d5c4c5de7722be8fAdam Lesinski    printf("Android Asset Packaging Tool, v0.2-" AAPT_VERSION "\n");
41282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
42282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return 0;
43282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
44282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
45282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
46282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
47282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Open the file read only.  The call fails if the file doesn't exist.
48282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
49282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Returns NULL on failure.
50282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
51282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiZipFile* openReadOnly(const char* fileName)
52282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
53282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ZipFile* zip;
54282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t result;
55282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
56282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    zip = new ZipFile;
57282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    result = zip->open(fileName, ZipFile::kOpenReadOnly);
58282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (result != NO_ERROR) {
59282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (result == NAME_NOT_FOUND) {
60282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: '%s' not found\n", fileName);
61282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else if (result == PERMISSION_DENIED) {
62282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: '%s' access denied\n", fileName);
63282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
64282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: failed opening '%s' as Zip file\n",
65282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fileName);
66282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
67282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        delete zip;
68282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NULL;
69282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
70282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
71282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return zip;
72282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
73282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
74282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
75282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Open the file read-write.  The file will be created if it doesn't
76282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * already exist and "okayToCreate" is set.
77282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
78282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Returns NULL on failure.
79282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
80282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiZipFile* openReadWrite(const char* fileName, bool okayToCreate)
81282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
82282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ZipFile* zip = NULL;
83282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t result;
84282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int flags;
85282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
86282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    flags = ZipFile::kOpenReadWrite;
87282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (okayToCreate) {
88282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        flags |= ZipFile::kOpenCreate;
89282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
90282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
91282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    zip = new ZipFile;
92282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    result = zip->open(fileName, flags);
93282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (result != NO_ERROR) {
94282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        delete zip;
95282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        zip = NULL;
96282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
97282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
98282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
99282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail:
100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return zip;
101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Return a short string describing the compression method.
106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiconst char* compressionName(int method)
108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (method == ZipEntry::kCompressStored) {
110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return "Stored";
111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else if (method == ZipEntry::kCompressDeflated) {
112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return "Deflated";
113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return "Unknown";
115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Return the percent reduction in size (0% == no compression).
120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint calcPercent(long uncompressedLen, long compressedLen)
122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (!uncompressedLen) {
124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return 0;
125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return (int) (100.0 - (compressedLen * 100.0) / uncompressedLen + 0.5);
127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Handle the "list" command, which can be a simple file dump or
132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * a verbose listing.
133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * The verbose listing closely matches the output of the Info-ZIP "unzip"
135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * command.
136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doList(Bundle* bundle)
138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int result = 1;
140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ZipFile* zip = NULL;
141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const ZipEntry* entry;
142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    long totalUncLen, totalCompLen;
143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char* zipFileName;
144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getFileSpecCount() != 1) {
146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: specify zip file name (only)\n");
147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    zipFileName = bundle->getFileSpecEntry(0);
150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    zip = openReadOnly(zipFileName);
152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (zip == NULL) {
153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int count, i;
157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getVerbose()) {
159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printf("Archive:  %s\n", zipFileName);
160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printf(
161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            " Length   Method    Size  Ratio   Offset      Date  Time  CRC-32    Name\n");
162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printf(
163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            "--------  ------  ------- -----  -------      ----  ----  ------    ----\n");
164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    totalUncLen = totalCompLen = 0;
167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    count = zip->getNumEntries();
169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (i = 0; i < count; i++) {
170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        entry = zip->getEntryByIndex(i);
171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (bundle->getVerbose()) {
172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            char dateBuf[32];
173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            time_t when;
174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            when = entry->getModWhen();
176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            strftime(dateBuf, sizeof(dateBuf), "%m-%d-%y %H:%M",
177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                localtime(&when));
178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("%8ld  %-7.7s %7ld %3d%%  %8zd  %s  %08lx  %s\n",
180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                (long) entry->getUncompressedLen(),
181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                compressionName(entry->getCompressionMethod()),
182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                (long) entry->getCompressedLen(),
183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                calcPercent(entry->getUncompressedLen(),
184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            entry->getCompressedLen()),
185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                (size_t) entry->getLFHOffset(),
186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                dateBuf,
187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                entry->getCRC32(),
188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                entry->getFileName());
189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("%s\n", entry->getFileName());
191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        totalUncLen += entry->getUncompressedLen();
194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        totalCompLen += entry->getCompressedLen();
195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getVerbose()) {
198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printf(
199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        "--------          -------  ---                            -------\n");
200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printf("%8ld          %7ld  %2d%%                            %d files\n",
201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            totalUncLen,
202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            totalCompLen,
203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            calcPercent(totalUncLen, totalCompLen),
204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            zip->getNumEntries());
205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getAndroidList()) {
208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        AssetManager assets;
209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!assets.addAssetPath(String8(zipFileName), NULL)) {
210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: list -a failed because assets could not be loaded\n");
211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const ResTable& res = assets.getResources(false);
215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (&res == NULL) {
216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("\nNo resource table found.\n");
217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#ifndef HAVE_ANDROID_OS
219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("\nResource table:\n");
220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            res.print(false);
221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif
222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Asset* manifestAsset = assets.openNonAsset("AndroidManifest.xml",
225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                   Asset::ACCESS_BUFFER);
226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (manifestAsset == NULL) {
227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("\nNo AndroidManifest.xml found.\n");
228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("\nAndroid manifest:\n");
230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ResXMLTree tree;
231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            tree.setTo(manifestAsset->getBuffer(true),
232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       manifestAsset->getLength());
233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printXMLBlock(&tree);
234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        delete manifestAsset;
236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    result = 0;
239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail:
241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    delete zip;
242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return result;
243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
245ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinskistatic void printResolvedResourceAttribute(const ResTable& resTable, const ResXMLTree& tree,
24676327314d2238e105f8b94909f9c0cf85caca318Maurice Chu        uint32_t attrRes, String8 attrLabel, String8* outError)
24776327314d2238e105f8b94909f9c0cf85caca318Maurice Chu{
24876327314d2238e105f8b94909f9c0cf85caca318Maurice Chu    Res_value value;
249ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski    AaptXml::getResolvedResourceAttribute(resTable, tree, attrRes, &value, outError);
25076327314d2238e105f8b94909f9c0cf85caca318Maurice Chu    if (*outError != "") {
25176327314d2238e105f8b94909f9c0cf85caca318Maurice Chu        *outError = "error print resolved resource attribute";
25276327314d2238e105f8b94909f9c0cf85caca318Maurice Chu        return;
25376327314d2238e105f8b94909f9c0cf85caca318Maurice Chu    }
25476327314d2238e105f8b94909f9c0cf85caca318Maurice Chu    if (value.dataType == Res_value::TYPE_STRING) {
255ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski        String8 result = AaptXml::getResolvedAttribute(resTable, tree, attrRes, outError);
2562675f769673f69b0661ddee346292f25cb30a296Maurice Chu        printf("%s='%s'", attrLabel.string(),
2572675f769673f69b0661ddee346292f25cb30a296Maurice Chu                ResTable::normalizeForOutput(result.string()).string());
25876327314d2238e105f8b94909f9c0cf85caca318Maurice Chu    } else if (Res_value::TYPE_FIRST_INT <= value.dataType &&
25976327314d2238e105f8b94909f9c0cf85caca318Maurice Chu            value.dataType <= Res_value::TYPE_LAST_INT) {
26076327314d2238e105f8b94909f9c0cf85caca318Maurice Chu        printf("%s='%d'", attrLabel.string(), value.data);
26176327314d2238e105f8b94909f9c0cf85caca318Maurice Chu    } else {
26276327314d2238e105f8b94909f9c0cf85caca318Maurice Chu        printf("%s='0x%x'", attrLabel.string(), (int)value.data);
26376327314d2238e105f8b94909f9c0cf85caca318Maurice Chu    }
26476327314d2238e105f8b94909f9c0cf85caca318Maurice Chu}
26576327314d2238e105f8b94909f9c0cf85caca318Maurice Chu
266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// These are attribute resource constants for the platform, as found
267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// in android.R.attr
268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskienum {
269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    LABEL_ATTR = 0x01010001,
270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ICON_ATTR = 0x01010002,
271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    NAME_ATTR = 0x01010003,
272a5018c900f126ee8424c82497f32983873db741bAdam Lesinski    PERMISSION_ATTR = 0x01010006,
2739d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski    EXPORTED_ATTR = 0x01010010,
2749d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski    GRANT_URI_PERMISSIONS_ATTR = 0x0101001b,
27594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    RESOURCE_ATTR = 0x01010025,
276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    DEBUGGABLE_ATTR = 0x0101000f,
277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    VALUE_ATTR = 0x01010024,
278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    VERSION_CODE_ATTR = 0x0101021b,
279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    VERSION_NAME_ATTR = 0x0101021c,
280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    SCREEN_ORIENTATION_ATTR = 0x0101001e,
281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    MIN_SDK_VERSION_ATTR = 0x0101020c,
282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    MAX_SDK_VERSION_ATTR = 0x01010271,
283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    REQ_TOUCH_SCREEN_ATTR = 0x01010227,
284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    REQ_KEYBOARD_TYPE_ATTR = 0x01010228,
285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    REQ_HARD_KEYBOARD_ATTR = 0x01010229,
286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    REQ_NAVIGATION_ATTR = 0x0101022a,
287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    REQ_FIVE_WAY_NAV_ATTR = 0x01010232,
288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    TARGET_SDK_VERSION_ATTR = 0x01010270,
289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    TEST_ONLY_ATTR = 0x01010272,
290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ANY_DENSITY_ATTR = 0x0101026c,
291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    GL_ES_VERSION_ATTR = 0x01010281,
292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    SMALL_SCREEN_ATTR = 0x01010284,
293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    NORMAL_SCREEN_ATTR = 0x01010285,
294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    LARGE_SCREEN_ATTR = 0x01010286,
295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    XLARGE_SCREEN_ATTR = 0x010102bf,
296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    REQUIRED_ATTR = 0x0101028e,
297caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski    INSTALL_LOCATION_ATTR = 0x010102b7,
298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    SCREEN_SIZE_ATTR = 0x010102ca,
299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    SCREEN_DENSITY_ATTR = 0x010102cb,
300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    REQUIRES_SMALLEST_WIDTH_DP_ATTR = 0x01010364,
301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    COMPATIBLE_WIDTH_LIMIT_DP_ATTR = 0x01010365,
302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    LARGEST_WIDTH_LIMIT_DP_ATTR = 0x01010366,
303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    PUBLIC_KEY_ATTR = 0x010103a6,
30494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    CATEGORY_ATTR = 0x010103e8,
3050a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn    BANNER_ATTR = 0x10103f2,
306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski};
307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3082675f769673f69b0661ddee346292f25cb30a296Maurice ChuString8 getComponentName(String8 &pkgName, String8 &componentName) {
309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t idx = componentName.find(".");
310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String8 retStr(pkgName);
311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (idx == 0) {
312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        retStr += componentName;
313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else if (idx < 0) {
314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        retStr += ".";
315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        retStr += componentName;
316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
3172675f769673f69b0661ddee346292f25cb30a296Maurice Chu        return componentName;
318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3192675f769673f69b0661ddee346292f25cb30a296Maurice Chu    return retStr;
320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3229cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinskistatic void printCompatibleScreens(ResXMLTree& tree, String8* outError) {
323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t len;
324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ResXMLTree::event_code_t code;
325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int depth = 0;
326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool first = true;
327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    printf("compatible-screens:");
328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (code == ResXMLTree::END_TAG) {
330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            depth--;
331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (depth < 0) {
332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                break;
333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (code != ResXMLTree::START_TAG) {
337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        depth++;
3409cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski        const char16_t* ctag16 = tree.getElementName(&len);
3419cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski        if (ctag16 == NULL) {
3429cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski            *outError = "failed to get XML element name (bad string pool)";
3439cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski            return;
3449cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski        }
3459cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski        String8 tag(ctag16);
346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (tag == "screen") {
347ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski            int32_t screenSize = AaptXml::getIntegerAttribute(tree,
348ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                    SCREEN_SIZE_ATTR);
349ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski            int32_t screenDensity = AaptXml::getIntegerAttribute(tree,
350ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                    SCREEN_DENSITY_ATTR);
351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (screenSize > 0 && screenDensity > 0) {
352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!first) {
353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    printf(",");
354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                first = false;
356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("'%d/%d'", screenSize, screenDensity);
357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    printf("\n");
361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
36358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinskistatic void printUsesPermission(const String8& name, bool optional=false, int maxSdkVersion=-1) {
36458f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski    printf("uses-permission: name='%s'", ResTable::normalizeForOutput(name.string()).string());
36558f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski    if (maxSdkVersion != -1) {
36658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski         printf(" maxSdkVersion='%d'", maxSdkVersion);
36758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski    }
36858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski    printf("\n");
36958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski
37058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski    if (optional) {
37158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski        printf("optional-permission: name='%s'",
37258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                ResTable::normalizeForOutput(name.string()).string());
37358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski        if (maxSdkVersion != -1) {
37458f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski            printf(" maxSdkVersion='%d'", maxSdkVersion);
37558f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski        }
37658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski        printf("\n");
37758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski    }
37858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski}
37958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski
38058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinskistatic void printUsesImpliedPermission(const String8& name, const String8& reason) {
38158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski    printf("uses-implied-permission: name='%s' reason='%s'\n",
38258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski            ResTable::normalizeForOutput(name.string()).string(),
38358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski            ResTable::normalizeForOutput(reason.string()).string());
38458f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski}
38558f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski
38694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam LesinskiVector<String8> getNfcAidCategories(AssetManager& assets, String8 xmlPath, bool offHost,
38794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski        String8 *outError = NULL)
38894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski{
38994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    Asset* aidAsset = assets.openNonAsset(xmlPath, Asset::ACCESS_BUFFER);
39094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    if (aidAsset == NULL) {
39194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski        if (outError != NULL) *outError = "xml resource does not exist";
39294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski        return Vector<String8>();
39394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    }
39494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
39594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    const String8 serviceTagName(offHost ? "offhost-apdu-service" : "host-apdu-service");
39694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
39794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    bool withinApduService = false;
39894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    Vector<String8> categories;
39994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
40094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    String8 error;
40194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    ResXMLTree tree;
40294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    tree.setTo(aidAsset->getBuffer(true), aidAsset->getLength());
40394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
40494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    size_t len;
40594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    int depth = 0;
40694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    ResXMLTree::event_code_t code;
40794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
40894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski        if (code == ResXMLTree::END_TAG) {
40994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            depth--;
4109cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski            const char16_t* ctag16 = tree.getElementName(&len);
4119cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski            if (ctag16 == NULL) {
4129cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                *outError = "failed to get XML element name (bad string pool)";
4139cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                return Vector<String8>();
4149cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski            }
4159cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski            String8 tag(ctag16);
41694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
41794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            if (depth == 0 && tag == serviceTagName) {
41894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                withinApduService = false;
41994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            }
42094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
42194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski        } else if (code == ResXMLTree::START_TAG) {
42294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            depth++;
4239cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski            const char16_t* ctag16 = tree.getElementName(&len);
4249cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski            if (ctag16 == NULL) {
4259cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                *outError = "failed to get XML element name (bad string pool)";
4269cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                return Vector<String8>();
4279cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski            }
4289cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski            String8 tag(ctag16);
42994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
43094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            if (depth == 1) {
43194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                if (tag == serviceTagName) {
43294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    withinApduService = true;
43394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                }
43494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            } else if (depth == 2 && withinApduService) {
43594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                if (tag == "aid-group") {
436ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                    String8 category = AaptXml::getAttribute(tree, CATEGORY_ATTR, &error);
43794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    if (error != "") {
43894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        if (outError != NULL) *outError = error;
43994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        return Vector<String8>();
44094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    }
44194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
44294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    categories.add(category);
44394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                }
44494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            }
44594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski        }
44694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    }
44794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    aidAsset->close();
44894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    return categories;
44994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski}
45094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
4519d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinskistatic void printComponentPresence(const char* componentName) {
4529d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski    printf("provides-component:'%s'\n", componentName);
4539d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski}
4549d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski
4552c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski/**
4562c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * Represents a feature that has been automatically added due to
4572c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * a pre-requisite or some other reason.
4582c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski */
4592c72b6822debb08fe997926eedc110f62d287d34Adam Lesinskistruct ImpliedFeature {
4602c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    /**
4612c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski     * Name of the implied feature.
4622c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski     */
4632c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    String8 name;
4642c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
4652c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    /**
4662c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski     * List of human-readable reasons for why this feature was implied.
4672c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski     */
4682c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    SortedVector<String8> reasons;
4692c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski};
4702c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
4712c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski/**
4722c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * Represents a <feature-group> tag in the AndroidManifest.xml
4732c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski */
4742c72b6822debb08fe997926eedc110f62d287d34Adam Lesinskistruct FeatureGroup {
475d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski    FeatureGroup() : openGLESVersion(-1) {}
476d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski
4772c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    /**
4782c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski     * Human readable label
4792c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski     */
4802c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    String8 label;
4812c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
4822c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    /**
4832c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski     * Explicit features defined in the group
4842c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski     */
4852c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    KeyedVector<String8, bool> features;
486d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski
487d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski    /**
488d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski     * OpenGL ES version required
489d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski     */
490d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski    int openGLESVersion;
4912c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski};
4922c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
4932c72b6822debb08fe997926eedc110f62d287d34Adam Lesinskistatic void addImpliedFeature(KeyedVector<String8, ImpliedFeature>* impliedFeatures,
4942c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        const char* name, const char* reason) {
4952c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    String8 name8(name);
4962c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    ssize_t idx = impliedFeatures->indexOfKey(name8);
4972c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    if (idx < 0) {
4982c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        idx = impliedFeatures->add(name8, ImpliedFeature());
4992c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        impliedFeatures->editValueAt(idx).name = name8;
5002c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    }
5012c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    impliedFeatures->editValueAt(idx).reasons.add(String8(reason));
5022c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski}
5032c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
5042c72b6822debb08fe997926eedc110f62d287d34Adam Lesinskistatic void printFeatureGroup(const FeatureGroup& grp,
5052c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        const KeyedVector<String8, ImpliedFeature>* impliedFeatures = NULL) {
5062c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    printf("feature-group: label='%s'\n", grp.label.string());
5072c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
508d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski    if (grp.openGLESVersion > 0) {
509d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski        printf("  uses-gl-es: '0x%x'\n", grp.openGLESVersion);
510d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski    }
511d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski
5122c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    const size_t numFeatures = grp.features.size();
5132c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    for (size_t i = 0; i < numFeatures; i++) {
5142c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        if (!grp.features[i]) {
5152c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski            continue;
5162c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        }
5172c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
5182c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        const String8& featureName = grp.features.keyAt(i);
5192c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        printf("  uses-feature: name='%s'\n",
5202c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                ResTable::normalizeForOutput(featureName.string()).string());
5212c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    }
5222c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
5232c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    const size_t numImpliedFeatures =
5242c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        (impliedFeatures != NULL) ? impliedFeatures->size() : 0;
5252c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    for (size_t i = 0; i < numImpliedFeatures; i++) {
5262c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        const ImpliedFeature& impliedFeature = impliedFeatures->valueAt(i);
5272c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        if (grp.features.indexOfKey(impliedFeature.name) >= 0) {
5282c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski            // The feature is explicitly set, no need to use implied
5292c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski            // definition.
5302c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski            continue;
5312c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        }
5322c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
5332c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        String8 printableFeatureName(ResTable::normalizeForOutput(
5342c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                    impliedFeature.name.string()));
5352c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        printf("  uses-feature: name='%s'\n", printableFeatureName.string());
5362c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        printf("  uses-implied-feature: name='%s' reason='",
5372c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                printableFeatureName.string());
5382c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        const size_t numReasons = impliedFeature.reasons.size();
5392c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        for (size_t j = 0; j < numReasons; j++) {
5402c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski            printf("%s", impliedFeature.reasons[j].string());
5412c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski            if (j + 2 < numReasons) {
5422c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                printf(", ");
5432c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski            } else if (j + 1 < numReasons) {
5442c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                printf(", and ");
5452c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski            }
5462c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        }
5472c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        printf("'\n");
5482c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    }
5492c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski}
5502c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
5512c72b6822debb08fe997926eedc110f62d287d34Adam Lesinskistatic void addParentFeatures(FeatureGroup* grp, const String8& name) {
5522c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    if (name == "android.hardware.camera.autofocus" ||
5532c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski            name == "android.hardware.camera.flash") {
5542c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        grp->features.add(String8("android.hardware.camera"), true);
5552c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    } else if (name == "android.hardware.location.gps" ||
5562c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski            name == "android.hardware.location.network") {
5572c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        grp->features.add(String8("android.hardware.location"), true);
5582c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    } else if (name == "android.hardware.touchscreen.multitouch") {
5592c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        grp->features.add(String8("android.hardware.touchscreen"), true);
5602c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    } else if (name == "android.hardware.touchscreen.multitouch.distinct") {
5612c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        grp->features.add(String8("android.hardware.touchscreen.multitouch"), true);
5622c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        grp->features.add(String8("android.hardware.touchscreen"), true);
563d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski    } else if (name == "android.hardware.opengles.aep") {
564d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski        const int openGLESVersion31 = 0x00030001;
565d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski        if (openGLESVersion31 > grp->openGLESVersion) {
566d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski            grp->openGLESVersion = openGLESVersion31;
567d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski        }
5682c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    }
5692c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski}
5702c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
571282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Handle the "dump" command, to extract select data from an archive.
573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiextern char CONSOLE_DATA[2925]; // see EOF
575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doDump(Bundle* bundle)
576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t result = UNKNOWN_ERROR;
578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getFileSpecCount() < 1) {
580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: no dump option specified\n");
581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return 1;
582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getFileSpecCount() < 2) {
585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: no dump file specified\n");
586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return 1;
587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char* option = bundle->getFileSpecEntry(0);
590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char* filename = bundle->getFileSpecEntry(1);
591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    AssetManager assets;
593f85e41f29a0e9313c2d4725f9d9648591ea49f3bNarayan Kamath    int32_t assetsCookie;
594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (!assets.addAssetPath(String8(filename), &assetsCookie)) {
595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: dump failed because assets could not be loaded\n");
596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return 1;
597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Make a dummy config for retrieving resources...  we need to supply
600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // non-default values for some configs so that we can retrieve resources
601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // in the app that don't have a default.  The most important of these is
602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // the API version because key resources like icons will have an implicit
603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // version if they are using newer config types like density.
604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ResTable_config config;
60591447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath    memset(&config, 0, sizeof(ResTable_config));
606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    config.language[0] = 'e';
607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    config.language[1] = 'n';
608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    config.country[0] = 'U';
609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    config.country[1] = 'S';
610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    config.orientation = ResTable_config::ORIENTATION_PORT;
611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    config.density = ResTable_config::DENSITY_MEDIUM;
612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    config.sdkVersion = 10000; // Very high.
613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    config.screenWidthDp = 320;
614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    config.screenHeightDp = 480;
615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    config.smallestScreenWidthDp = 320;
616c2dea8daea2ae0001d56689d96ce1066012b7b40Adam Lesinski    config.screenLayout |= ResTable_config::SCREENSIZE_NORMAL;
617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    assets.setConfiguration(config);
618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const ResTable& res = assets.getResources(false);
620282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (&res == NULL) {
621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: dump failed because no resource table was found\n");
62263e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski        return 1;
62325e9d55e964c180ec6e57ba1d977d6c2e1115f5aAdam Lesinski    } else if (res.getError() != NO_ERROR) {
62425e9d55e964c180ec6e57ba1d977d6c2e1115f5aAdam Lesinski        fprintf(stderr, "ERROR: dump failed because the resource table is invalid/corrupt.\n");
62563e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski        return 1;
62663e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski    }
62763e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski
6282cb761e3ddb9d68ab430013e9cd15ecaab9fbc62Adam Lesinski    // The dynamicRefTable can be null if there are no resources for this asset cookie.
6292cb761e3ddb9d68ab430013e9cd15ecaab9fbc62Adam Lesinski    // This fine.
63063e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski    const DynamicRefTable* dynamicRefTable = res.getDynamicRefTableForCookie(assetsCookie);
631282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
63263e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski    Asset* asset = NULL;
63363e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski
634282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (strcmp("resources", option) == 0) {
635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#ifndef HAVE_ANDROID_OS
636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        res.print(bundle->getValues());
637282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif
638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else if (strcmp("strings", option) == 0) {
640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const ResStringPool* pool = res.getTableStringBlock(0);
641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printStringPool(pool);
642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else if (strcmp("xmltree", option) == 0) {
644282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (bundle->getFileSpecCount() < 3) {
645282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: no dump xmltree resource file specified\n");
646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
648282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (int i=2; i<bundle->getFileSpecCount(); i++) {
650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const char* resname = bundle->getFileSpecEntry(i);
65163e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski            ResXMLTree tree(dynamicRefTable);
65263e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski            asset = assets.openNonAsset(assetsCookie, resname, Asset::ACCESS_BUFFER);
653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (asset == NULL) {
654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, "ERROR: dump failed because resource %s found\n", resname);
655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                goto bail;
656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (tree.setTo(asset->getBuffer(true),
659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           asset->getLength()) != NO_ERROR) {
660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, "ERROR: Resource %s is corrupt\n", resname);
661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                goto bail;
662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            tree.restart();
664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printXMLBlock(&tree);
665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            tree.uninit();
666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            delete asset;
667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            asset = NULL;
668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else if (strcmp("xmlstrings", option) == 0) {
671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (bundle->getFileSpecCount() < 3) {
672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: no dump xmltree resource file specified\n");
673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
676282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (int i=2; i<bundle->getFileSpecCount(); i++) {
677282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const char* resname = bundle->getFileSpecEntry(i);
67863e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski            asset = assets.openNonAsset(assetsCookie, resname, Asset::ACCESS_BUFFER);
679282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (asset == NULL) {
680282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, "ERROR: dump failed because resource %s found\n", resname);
681282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                goto bail;
682282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
683282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
68463e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski            ResXMLTree tree(dynamicRefTable);
685282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (tree.setTo(asset->getBuffer(true),
686282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           asset->getLength()) != NO_ERROR) {
687282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, "ERROR: Resource %s is corrupt\n", resname);
688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                goto bail;
689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
690282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printStringPool(&tree.getStrings());
691282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            delete asset;
692282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            asset = NULL;
693282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
694282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
69663e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski        asset = assets.openNonAsset(assetsCookie, "AndroidManifest.xml", Asset::ACCESS_BUFFER);
697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (asset == NULL) {
698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: dump failed because no AndroidManifest.xml found\n");
699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
700282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
70263e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski        ResXMLTree tree(dynamicRefTable);
703282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (tree.setTo(asset->getBuffer(true),
704282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       asset->getLength()) != NO_ERROR) {
705282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: AndroidManifest.xml is corrupt\n");
706282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
707282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
708282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        tree.restart();
709282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
710282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (strcmp("permissions", option) == 0) {
711282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            size_t len;
712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ResXMLTree::event_code_t code;
713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int depth = 0;
714282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (code == ResXMLTree::END_TAG) {
716282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    depth--;
717282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
718282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
719282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (code != ResXMLTree::START_TAG) {
720282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
721282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
722282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                depth++;
7239cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                const char16_t* ctag16 = tree.getElementName(&len);
7249cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                if (ctag16 == NULL) {
7259cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                    fprintf(stderr, "ERROR: failed to get XML element name (bad string pool)\n");
7269cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                    goto bail;
7279cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                }
7289cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                String8 tag(ctag16);
729282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                //printf("Depth %d tag %s\n", depth, tag.string());
730282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (depth == 1) {
731282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (tag != "manifest") {
732282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n");
733282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        goto bail;
734282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
735ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                    String8 pkg = AaptXml::getAttribute(tree, NULL, "package", NULL);
7362675f769673f69b0661ddee346292f25cb30a296Maurice Chu                    printf("package: %s\n", ResTable::normalizeForOutput(pkg.string()).string());
737282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else if (depth == 2 && tag == "permission") {
738282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8 error;
739ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                    String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
740282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (error != "") {
741282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        fprintf(stderr, "ERROR: %s\n", error.string());
742282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        goto bail;
743282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
7442675f769673f69b0661ddee346292f25cb30a296Maurice Chu                    printf("permission: %s\n",
7452675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            ResTable::normalizeForOutput(name.string()).string());
746282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else if (depth == 2 && tag == "uses-permission") {
747282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8 error;
748ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                    String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
749282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (error != "") {
750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        fprintf(stderr, "ERROR: %s\n", error.string());
751282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        goto bail;
752282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
75358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesPermission(name,
754ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            AaptXml::getIntegerAttribute(tree, REQUIRED_ATTR, 1) == 0,
755ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            AaptXml::getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR));
756282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
757282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
758282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else if (strcmp("badging", option) == 0) {
759282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Vector<String8> locales;
760282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            res.getLocales(&locales);
761282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
762282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Vector<ResTable_config> configs;
763282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            res.getConfigurations(&configs);
764282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            SortedVector<int> densities;
765282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t NC = configs.size();
766282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t i=0; i<NC; i++) {
767282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                int dens = configs[i].density;
768282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (dens == 0) {
769282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    dens = 160;
770282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
771282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                densities.add(dens);
772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
774282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            size_t len;
775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ResXMLTree::event_code_t code;
776282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int depth = 0;
777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 error;
778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool withinActivity = false;
779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool isMainActivity = false;
780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool isLauncherActivity = false;
7810a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn            bool isLeanbackLauncherActivity = false;
782282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool isSearchable = false;
783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool withinApplication = false;
784ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright            bool withinSupportsInput = false;
7852c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski            bool withinFeatureGroup = false;
786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool withinReceiver = false;
787282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool withinService = false;
7889d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool withinProvider = false;
789282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool withinIntentFilter = false;
790282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasMainActivity = false;
791282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasOtherActivities = false;
792282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasOtherReceivers = false;
793282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasOtherServices = false;
7949d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool hasIntentFilter = false;
7959d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski
796282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasWallpaperService = false;
797282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasImeService = false;
798a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool hasAccessibilityService = false;
799a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool hasPrintService = false;
800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasWidgetReceivers = false;
801a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool hasDeviceAdminReceiver = false;
80294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            bool hasPaymentService = false;
8039d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool hasDocumentsProvider = false;
8049d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool hasCameraActivity = false;
8059d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool hasCameraSecureActivity = false;
8069d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool hasLauncher = false;
8079d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool hasNotificationListenerService = false;
808eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock            bool hasDreamService = false;
8099d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski
810282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool actMainActivity = false;
811282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool actWidgetReceivers = false;
812a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool actDeviceAdminEnabled = false;
813282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool actImeService = false;
814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool actWallpaperService = false;
815a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool actAccessibilityService = false;
816a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool actPrintService = false;
81794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            bool actHostApduService = false;
81894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            bool actOffHostApduService = false;
8199d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool actDocumentsProvider = false;
8209d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool actNotificationListenerService = false;
821eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock            bool actDreamService = false;
8229d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool actCamera = false;
8239d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool actCameraSecure = false;
8249d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool catLauncher = false;
82594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            bool hasMetaHostPaymentCategory = false;
82694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            bool hasMetaOffHostPaymentCategory = false;
827a5018c900f126ee8424c82497f32983873db741bAdam Lesinski
828a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            // These permissions are required by services implementing services
829a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            // the system binds to (IME, Accessibility, PrintServices, etc.)
830a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool hasBindDeviceAdminPermission = false;
831a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool hasBindInputMethodPermission = false;
832a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool hasBindAccessibilityServicePermission = false;
833a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool hasBindPrintServicePermission = false;
83494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            bool hasBindNfcServicePermission = false;
8359d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool hasRequiredSafAttributes = false;
8369d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool hasBindNotificationListenerServicePermission = false;
837eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock            bool hasBindDreamServicePermission = false;
838282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
839282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // These two implement the implicit permissions that are granted
840282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // to pre-1.6 applications.
841282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasWriteExternalStoragePermission = false;
842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasReadPhoneStatePermission = false;
843282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
844282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // If an app requests write storage, they will also get read storage.
845282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasReadExternalStoragePermission = false;
846282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
847282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Implement transition to read and write call log.
848282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasReadContactsPermission = false;
849282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasWriteContactsPermission = false;
850282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasReadCallLogPermission = false;
851282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasWriteCallLogPermission = false;
852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
853e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski            // If an app declares itself as multiArch, we report the
854e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski            // native libraries differently.
855e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski            bool hasMultiArch = false;
856e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski
857282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // This next group of variables is used to implement a group of
858282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // backward-compatibility heuristics necessitated by the addition of
859282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // some new uses-feature constants in 2.1 and 2.2. In most cases, the
860282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // heuristic is "if an app requests a permission but doesn't explicitly
861282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // request the corresponding <uses-feature>, presume it's there anyway".
8622c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
863282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // 2.2 also added some other features that apps can request, but that
864282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // have no corresponding permission, so we cannot implement any
865282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // back-compatibility heuristic for them. The below are thus unnecessary
866282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // (but are retained here for documentary purposes.)
867282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //bool specCompassFeature = false;
868282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //bool specAccelerometerFeature = false;
869282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //bool specProximityFeature = false;
870282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //bool specAmbientLightFeature = false;
871282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //bool specLiveWallpaperFeature = false;
872282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
873282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int targetSdk = 0;
874282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int smallScreen = 1;
875282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int normalScreen = 1;
876282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int largeScreen = 1;
877282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int xlargeScreen = 1;
878282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int anyDensity = 1;
879282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int requiresSmallestWidthDp = 0;
880282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int compatibleWidthLimitDp = 0;
881282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int largestWidthLimitDp = 0;
882282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 pkg;
883282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 activityName;
884282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 activityLabel;
885282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 activityIcon;
8860a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn            String8 activityBanner;
887282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 receiverName;
888282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 serviceName;
889ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright            Vector<String8> supportedInput;
8902c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
8912c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski            FeatureGroup commonFeatures;
8922c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski            Vector<FeatureGroup> featureGroups;
8932c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski            KeyedVector<String8, ImpliedFeature> impliedFeatures;
8942c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
895282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
896282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (code == ResXMLTree::END_TAG) {
897282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    depth--;
898282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (depth < 2) {
899ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        if (withinSupportsInput && !supportedInput.isEmpty()) {
900ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            printf("supports-input: '");
901ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            const size_t N = supportedInput.size();
902ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            for (size_t i=0; i<N; i++) {
9032675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                printf("%s", ResTable::normalizeForOutput(
9042675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                        supportedInput[i].string()).string());
905ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                if (i != N - 1) {
906ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                    printf("' '");
907ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                } else {
908ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                    printf("'\n");
909ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                }
910ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
911ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            supportedInput.clear();
912ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        }
913282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        withinApplication = false;
914ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        withinSupportsInput = false;
9152c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                        withinFeatureGroup = false;
916282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (depth < 3) {
9170a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                        if (withinActivity && isMainActivity) {
9182675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            String8 aName(getComponentName(pkg, activityName));
9190a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                            if (isLauncherActivity) {
9200a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                printf("launchable-activity:");
9219eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                if (aName.length() > 0) {
9229eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                    printf(" name='%s' ",
9239eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                            ResTable::normalizeForOutput(aName.string()).string());
9240a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                }
9250a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                printf(" label='%s' icon='%s'\n",
9269eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                        ResTable::normalizeForOutput(activityLabel.string()).string(),
9279eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                        ResTable::normalizeForOutput(activityIcon.string()).string());
9280a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                            }
9290a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                            if (isLeanbackLauncherActivity) {
9300a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                printf("leanback-launchable-activity:");
9319eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                if (aName.length() > 0) {
9329eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                    printf(" name='%s' ",
9339eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                            ResTable::normalizeForOutput(aName.string()).string());
9340a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                }
9350a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                printf(" label='%s' icon='%s' banner='%s'\n",
9369eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                        ResTable::normalizeForOutput(activityLabel.string()).string(),
9379eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                        ResTable::normalizeForOutput(activityIcon.string()).string(),
9389eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                        ResTable::normalizeForOutput(activityBanner.string()).string());
939282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
940282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
941282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (!hasIntentFilter) {
942282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            hasOtherActivities |= withinActivity;
943282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            hasOtherReceivers |= withinReceiver;
944282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            hasOtherServices |= withinService;
94594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        } else {
94694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            if (withinService) {
94794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                hasPaymentService |= (actHostApduService && hasMetaHostPaymentCategory &&
94894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                        hasBindNfcServicePermission);
94994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                hasPaymentService |= (actOffHostApduService && hasMetaOffHostPaymentCategory &&
95094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                        hasBindNfcServicePermission);
95194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            }
952282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
953282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        withinActivity = false;
954282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        withinService = false;
955282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        withinReceiver = false;
9569d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                        withinProvider = false;
957282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasIntentFilter = false;
9580a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                        isMainActivity = isLauncherActivity = isLeanbackLauncherActivity = false;
959282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (depth < 4) {
960282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (withinIntentFilter) {
961282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (withinActivity) {
962282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasMainActivity |= actMainActivity;
9639d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                hasLauncher |= catLauncher;
9649d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                hasCameraActivity |= actCamera;
9659d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                hasCameraSecureActivity |= actCameraSecure;
9669d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                hasOtherActivities |= !actMainActivity && !actCamera && !actCameraSecure;
967282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (withinReceiver) {
968282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasWidgetReceivers |= actWidgetReceivers;
969a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                hasDeviceAdminReceiver |= (actDeviceAdminEnabled &&
970a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                        hasBindDeviceAdminPermission);
971a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                hasOtherReceivers |= (!actWidgetReceivers && !actDeviceAdminEnabled);
972282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (withinService) {
973282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasImeService |= actImeService;
974282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasWallpaperService |= actWallpaperService;
975a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                hasAccessibilityService |= (actAccessibilityService &&
976a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                        hasBindAccessibilityServicePermission);
977a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                hasPrintService |= (actPrintService && hasBindPrintServicePermission);
9789d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                hasNotificationListenerService |= actNotificationListenerService &&
9799d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                        hasBindNotificationListenerServicePermission;
980eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock                                hasDreamService |= actDreamService && hasBindDreamServicePermission;
981a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                hasOtherServices |= (!actImeService && !actWallpaperService &&
98294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                        !actAccessibilityService && !actPrintService &&
9839d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                        !actHostApduService && !actOffHostApduService &&
9849d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                        !actNotificationListenerService);
9859d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            } else if (withinProvider) {
9869d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                hasDocumentsProvider |= actDocumentsProvider && hasRequiredSafAttributes;
987282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
988282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
989282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        withinIntentFilter = false;
990282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
991282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
992282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
993282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (code != ResXMLTree::START_TAG) {
994282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
995282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
996282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                depth++;
9979cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski
9989cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                const char16_t* ctag16 = tree.getElementName(&len);
9999cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                if (ctag16 == NULL) {
10009cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                    fprintf(stderr, "ERROR: failed to get XML element name (bad string pool)\n");
10019cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                    goto bail;
10029cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                }
10039cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                String8 tag(ctag16);
1004282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                //printf("Depth %d,  %s\n", depth, tag.string());
1005282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (depth == 1) {
1006282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (tag != "manifest") {
1007282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n");
1008282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        goto bail;
1009282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1010ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                    pkg = AaptXml::getAttribute(tree, NULL, "package", NULL);
10112675f769673f69b0661ddee346292f25cb30a296Maurice Chu                    printf("package: name='%s' ",
10122675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            ResTable::normalizeForOutput(pkg.string()).string());
1013ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                    int32_t versionCode = AaptXml::getIntegerAttribute(tree, VERSION_CODE_ATTR,
1014ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            &error);
1015282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (error != "") {
1016ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        fprintf(stderr, "ERROR getting 'android:versionCode' attribute: %s\n",
1017ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                error.string());
1018282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        goto bail;
1019282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1020282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (versionCode > 0) {
1021282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        printf("versionCode='%d' ", versionCode);
1022282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else {
1023282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        printf("versionCode='' ");
1024282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1025ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                    String8 versionName = AaptXml::getResolvedAttribute(res, tree,
1026ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            VERSION_NAME_ATTR, &error);
1027282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (error != "") {
1028ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        fprintf(stderr, "ERROR getting 'android:versionName' attribute: %s\n",
1029ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                error.string());
1030282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        goto bail;
1031282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
103225d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski                    printf("versionName='%s'",
10332675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            ResTable::normalizeForOutput(versionName.string()).string());
103425d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski
1035ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                    String8 splitName = AaptXml::getAttribute(tree, NULL, "split");
103625d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski                    if (!splitName.isEmpty()) {
103725d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski                        printf(" split='%s'", ResTable::normalizeForOutput(
103825d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski                                    splitName.string()).string());
103925d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski                    }
1040ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski
1041ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                    int32_t platformVersionCode = AaptXml::getIntegerAttribute(tree, NULL,
1042ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            "platformBuildVersionCode");
1043ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                    printf(" platformBuildVersionCode='%d'", platformVersionCode);
104425d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski                    printf("\n");
1045caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski
1046ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                    int32_t installLocation = AaptXml::getResolvedIntegerAttribute(res, tree,
1047ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            INSTALL_LOCATION_ATTR, &error);
1048caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                    if (error != "") {
1049caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                        fprintf(stderr, "ERROR getting 'android:installLocation' attribute: %s\n",
1050caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                                error.string());
1051caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                        goto bail;
1052caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                    }
1053caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski
1054caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                    if (installLocation >= 0) {
1055caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                        printf("install-location:'");
1056caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                        switch (installLocation) {
1057caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                            case 0:
1058caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                                printf("auto");
1059caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                                break;
1060caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                            case 1:
1061caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                                printf("internalOnly");
1062caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                                break;
1063caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                            case 2:
1064caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                                printf("preferExternal");
1065caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                                break;
1066caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                            default:
1067caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                                fprintf(stderr, "Invalid installLocation %d\n", installLocation);
1068caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                                goto bail;
1069caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                        }
1070caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                        printf("'\n");
1071caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                    }
1072282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else if (depth == 2) {
1073282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    withinApplication = false;
1074282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (tag == "application") {
1075282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        withinApplication = true;
1076282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1077282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8 label;
1078282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const size_t NL = locales.size();
1079282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        for (size_t i=0; i<NL; i++) {
1080282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            const char* localeStr =  locales[i].string();
1081282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            assets.setLocale(localeStr != NULL ? localeStr : "");
1082ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            String8 llabel = AaptXml::getResolvedAttribute(res, tree, LABEL_ATTR,
1083ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    &error);
1084282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (llabel != "") {
1085282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                if (localeStr == NULL || strlen(localeStr) == 0) {
1086282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    label = llabel;
10872675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                    printf("application-label:'%s'\n",
10882675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                            ResTable::normalizeForOutput(llabel.string()).string());
1089282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                } else {
1090282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    if (label == "") {
1091282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        label = llabel;
1092282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    }
1093282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    printf("application-label-%s:'%s'\n", localeStr,
10942675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                           ResTable::normalizeForOutput(llabel.string()).string());
1095282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                }
1096282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1097282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1098282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1099282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ResTable_config tmpConfig = config;
1100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const size_t ND = densities.size();
1101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        for (size_t i=0; i<ND; i++) {
1102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            tmpConfig.density = densities[i];
1103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            assets.setConfiguration(tmpConfig);
1104ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            String8 icon = AaptXml::getResolvedAttribute(res, tree, ICON_ATTR,
1105ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    &error);
1106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (icon != "") {
11072675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                printf("application-icon-%d:'%s'\n", densities[i],
11082675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                        ResTable::normalizeForOutput(icon.string()).string());
1109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        assets.setConfiguration(config);
1112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1113ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        String8 icon = AaptXml::getResolvedAttribute(res, tree, ICON_ATTR, &error);
1114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (error != "") {
1115ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n",
1116ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    error.string());
1117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            goto bail;
1118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1119ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        int32_t testOnly = AaptXml::getIntegerAttribute(tree, TEST_ONLY_ATTR, 0,
1120ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                &error);
1121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (error != "") {
1122ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            fprintf(stderr, "ERROR getting 'android:testOnly' attribute: %s\n",
1123ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    error.string());
1124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            goto bail;
1125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
11262675f769673f69b0661ddee346292f25cb30a296Maurice Chu                        printf("application: label='%s' ",
11272675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                ResTable::normalizeForOutput(label.string()).string());
11282675f769673f69b0661ddee346292f25cb30a296Maurice Chu                        printf("icon='%s'\n", ResTable::normalizeForOutput(icon.string()).string());
1129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (testOnly != 0) {
1130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf("testOnly='%d'\n", testOnly);
1131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1133ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        int32_t debuggable = AaptXml::getResolvedIntegerAttribute(res, tree,
1134ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                DEBUGGABLE_ATTR, 0, &error);
1135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (error != "") {
1136ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            fprintf(stderr, "ERROR getting 'android:debuggable' attribute: %s\n",
1137ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    error.string());
1138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            goto bail;
1139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (debuggable != 0) {
1141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf("application-debuggable\n");
1142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1143e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski
1144e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        // We must search by name because the multiArch flag hasn't been API
1145e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        // frozen yet.
1146e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        int32_t multiArchIndex = tree.indexOfAttribute(RESOURCES_ANDROID_NAMESPACE,
1147e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                                "multiArch");
1148e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        if (multiArchIndex >= 0) {
1149e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                            Res_value value;
1150e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                            if (tree.getAttributeValue(multiArchIndex, &value) != NO_ERROR) {
1151e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                                if (value.dataType >= Res_value::TYPE_FIRST_INT &&
1152e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                                        value.dataType <= Res_value::TYPE_LAST_INT) {
1153e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                                    hasMultiArch = value.data;
1154e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                                }
1155e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                            }
1156e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        }
1157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "uses-sdk") {
1158ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        int32_t code = AaptXml::getIntegerAttribute(tree, MIN_SDK_VERSION_ATTR, &error);
1159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (error != "") {
1160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            error = "";
1161ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            String8 name = AaptXml::getResolvedAttribute(res, tree,
1162ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    MIN_SDK_VERSION_ATTR, &error);
1163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (error != "") {
1164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                fprintf(stderr, "ERROR getting 'android:minSdkVersion' attribute: %s\n",
1165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        error.string());
1166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                goto bail;
1167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (name == "Donut") targetSdk = 4;
11692675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            printf("sdkVersion:'%s'\n",
11702675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                    ResTable::normalizeForOutput(name.string()).string());
1171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else if (code != -1) {
1172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            targetSdk = code;
1173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf("sdkVersion:'%d'\n", code);
1174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1175ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        code = AaptXml::getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR);
1176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (code != -1) {
1177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf("maxSdkVersion:'%d'\n", code);
1178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1179ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        code = AaptXml::getIntegerAttribute(tree, TARGET_SDK_VERSION_ATTR, &error);
1180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (error != "") {
1181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            error = "";
1182ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            String8 name = AaptXml::getResolvedAttribute(res, tree,
1183ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    TARGET_SDK_VERSION_ATTR, &error);
1184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (error != "") {
1185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                fprintf(stderr, "ERROR getting 'android:targetSdkVersion' attribute: %s\n",
1186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        error.string());
1187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                goto bail;
1188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (name == "Donut" && targetSdk < 4) targetSdk = 4;
11902675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            printf("targetSdkVersion:'%s'\n",
11912675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                    ResTable::normalizeForOutput(name.string()).string());
1192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else if (code != -1) {
1193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (targetSdk < code) {
1194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                targetSdk = code;
1195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf("targetSdkVersion:'%d'\n", code);
1197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "uses-configuration") {
1199ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        int32_t reqTouchScreen = AaptXml::getIntegerAttribute(tree,
1200ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                REQ_TOUCH_SCREEN_ATTR, 0);
1201ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        int32_t reqKeyboardType = AaptXml::getIntegerAttribute(tree,
1202ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                REQ_KEYBOARD_TYPE_ATTR, 0);
1203ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        int32_t reqHardKeyboard = AaptXml::getIntegerAttribute(tree,
1204ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                REQ_HARD_KEYBOARD_ATTR, 0);
1205ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        int32_t reqNavigation = AaptXml::getIntegerAttribute(tree,
1206ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                REQ_NAVIGATION_ATTR, 0);
1207ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        int32_t reqFiveWayNav = AaptXml::getIntegerAttribute(tree,
1208ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                REQ_FIVE_WAY_NAV_ATTR, 0);
1209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        printf("uses-configuration:");
1210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (reqTouchScreen != 0) {
1211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf(" reqTouchScreen='%d'", reqTouchScreen);
1212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (reqKeyboardType != 0) {
1214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf(" reqKeyboardType='%d'", reqKeyboardType);
1215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (reqHardKeyboard != 0) {
1217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf(" reqHardKeyboard='%d'", reqHardKeyboard);
1218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (reqNavigation != 0) {
1220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf(" reqNavigation='%d'", reqNavigation);
1221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (reqFiveWayNav != 0) {
1223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf(" reqFiveWayNav='%d'", reqFiveWayNav);
1224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        printf("\n");
1226ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                    } else if (tag == "supports-input") {
1227ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        withinSupportsInput = true;
1228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "supports-screens") {
1229ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        smallScreen = AaptXml::getIntegerAttribute(tree,
1230ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                SMALL_SCREEN_ATTR, 1);
1231ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        normalScreen = AaptXml::getIntegerAttribute(tree,
1232ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                NORMAL_SCREEN_ATTR, 1);
1233ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        largeScreen = AaptXml::getIntegerAttribute(tree,
1234ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                LARGE_SCREEN_ATTR, 1);
1235ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        xlargeScreen = AaptXml::getIntegerAttribute(tree,
1236ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                XLARGE_SCREEN_ATTR, 1);
1237ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        anyDensity = AaptXml::getIntegerAttribute(tree,
1238ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                ANY_DENSITY_ATTR, 1);
1239ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        requiresSmallestWidthDp = AaptXml::getIntegerAttribute(tree,
1240ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                REQUIRES_SMALLEST_WIDTH_DP_ATTR, 0);
1241ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        compatibleWidthLimitDp = AaptXml::getIntegerAttribute(tree,
1242ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                COMPATIBLE_WIDTH_LIMIT_DP_ATTR, 0);
1243ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        largestWidthLimitDp = AaptXml::getIntegerAttribute(tree,
1244ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                LARGEST_WIDTH_LIMIT_DP_ATTR, 0);
12452c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                    } else if (tag == "feature-group") {
12462c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                        withinFeatureGroup = true;
12472c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                        FeatureGroup group;
1248ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        group.label = AaptXml::getResolvedAttribute(res, tree, LABEL_ATTR, &error);
12492c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                        if (error != "") {
12502c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                            fprintf(stderr, "ERROR getting 'android:label' attribute:"
12512c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                    " %s\n", error.string());
12522c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                            goto bail;
12532c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                        }
12542c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                        featureGroups.add(group);
12552c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
1256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "uses-feature") {
1257ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
1258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (name != "" && error == "") {
1259ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            int req = AaptXml::getIntegerAttribute(tree,
1260ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    REQUIRED_ATTR, 1);
1261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
12622c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                            commonFeatures.features.add(name, req);
12632c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                            if (req) {
12642c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                addParentFeatures(&commonFeatures, name);
1265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else {
1267ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            int vers = AaptXml::getIntegerAttribute(tree,
1268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    GL_ES_VERSION_ATTR, &error);
1269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (error == "") {
1270d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                                if (vers > commonFeatures.openGLESVersion) {
1271d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                                    commonFeatures.openGLESVersion = vers;
1272d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                                }
1273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "uses-permission") {
1276ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
1277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (name != "" && error == "") {
1278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (name == "android.permission.CAMERA") {
1279d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                                addImpliedFeature(&impliedFeatures, "android.hardware.camera",
12802c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        String8::format("requested %s permission", name.string())
12812c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        .string());
1282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.ACCESS_FINE_LOCATION") {
12832c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                addImpliedFeature(&impliedFeatures, "android.hardware.location.gps",
12842c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        String8::format("requested %s permission", name.string())
12852c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        .string());
12862c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                addImpliedFeature(&impliedFeatures, "android.hardware.location",
12872c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        String8::format("requested %s permission", name.string())
12882c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        .string());
1289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.ACCESS_MOCK_LOCATION") {
12902c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                addImpliedFeature(&impliedFeatures, "android.hardware.location",
12912c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        String8::format("requested %s permission", name.string())
12922c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        .string());
1293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.ACCESS_COARSE_LOCATION") {
12942c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                addImpliedFeature(&impliedFeatures, "android.hardware.location.network",
12952c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        String8::format("requested %s permission", name.string())
12962c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        .string());
12972c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                addImpliedFeature(&impliedFeatures, "android.hardware.location",
12982c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        String8::format("requested %s permission", name.string())
12992c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        .string());
1300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" ||
1301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.INSTALL_LOCATION_PROVIDER") {
13022c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                addImpliedFeature(&impliedFeatures, "android.hardware.location",
13032c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        String8::format("requested %s permission", name.string())
13042c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        .string());
1305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.BLUETOOTH" ||
1306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.BLUETOOTH_ADMIN") {
13072c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                if (targetSdk > 4) {
13082c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                    addImpliedFeature(&impliedFeatures, "android.hardware.bluetooth",
13092c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                            String8::format("requested %s permission", name.string())
13102c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                            .string());
13112c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                    addImpliedFeature(&impliedFeatures, "android.hardware.bluetooth",
13122c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                            "targetSdkVersion > 4");
13132c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                }
1314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.RECORD_AUDIO") {
13152c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                addImpliedFeature(&impliedFeatures, "android.hardware.microphone",
13162c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        String8::format("requested %s permission", name.string())
13172c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        .string());
1318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.ACCESS_WIFI_STATE" ||
1319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.CHANGE_WIFI_STATE" ||
1320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.CHANGE_WIFI_MULTICAST_STATE") {
13212c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                addImpliedFeature(&impliedFeatures, "android.hardware.wifi",
13222c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        String8::format("requested %s permission", name.string())
13232c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        .string());
1324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.CALL_PHONE" ||
1325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.CALL_PRIVILEGED" ||
1326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.MODIFY_PHONE_STATE" ||
1327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.PROCESS_OUTGOING_CALLS" ||
1328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.READ_SMS" ||
1329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.RECEIVE_SMS" ||
1330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.RECEIVE_MMS" ||
1331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.RECEIVE_WAP_PUSH" ||
1332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.SEND_SMS" ||
1333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.WRITE_APN_SETTINGS" ||
1334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.WRITE_SMS") {
13352c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                addImpliedFeature(&impliedFeatures, "android.hardware.telephony",
13362c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        String8("requested a telephony permission").string());
1337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.WRITE_EXTERNAL_STORAGE") {
1338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasWriteExternalStoragePermission = true;
1339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.READ_EXTERNAL_STORAGE") {
1340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasReadExternalStoragePermission = true;
1341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.READ_PHONE_STATE") {
1342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasReadPhoneStatePermission = true;
1343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.READ_CONTACTS") {
1344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasReadContactsPermission = true;
1345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.WRITE_CONTACTS") {
1346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasWriteContactsPermission = true;
1347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.READ_CALL_LOG") {
1348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasReadCallLogPermission = true;
1349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.WRITE_CALL_LOG") {
1350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasWriteCallLogPermission = true;
1351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
135258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski
135358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                            printUsesPermission(name,
1354ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    AaptXml::getIntegerAttribute(tree, REQUIRED_ATTR, 1) == 0,
1355ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    AaptXml::getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR));
135658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                       } else {
1357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    error.string());
1359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            goto bail;
1360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "uses-package") {
1362ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
1363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (name != "" && error == "") {
13642675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            printf("uses-package:'%s'\n",
13652675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                    ResTable::normalizeForOutput(name.string()).string());
1366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else {
1367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    error.string());
1369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                goto bail;
1370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "original-package") {
1372ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
1373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (name != "" && error == "") {
13742675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            printf("original-package:'%s'\n",
13752675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                    ResTable::normalizeForOutput(name.string()).string());
1376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else {
1377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    error.string());
1379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                goto bail;
1380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "supports-gl-texture") {
1382ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
1383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (name != "" && error == "") {
13842675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            printf("supports-gl-texture:'%s'\n",
13852675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                    ResTable::normalizeForOutput(name.string()).string());
1386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else {
1387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    error.string());
1389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                goto bail;
1390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "compatible-screens") {
13929cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                        printCompatibleScreens(tree, &error);
13939cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                        if (error != "") {
13949cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                            fprintf(stderr, "ERROR getting compatible screens: %s\n",
13959cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                                    error.string());
13969cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                            goto bail;
13979cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                        }
1398282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        depth--;
1399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "package-verifier") {
1400ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
1401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (name != "" && error == "") {
1402ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            String8 publicKey = AaptXml::getAttribute(tree, PUBLIC_KEY_ATTR, &error);
1403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (publicKey != "" && error == "") {
1404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                printf("package-verifier: name='%s' publicKey='%s'\n",
14052675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                        ResTable::normalizeForOutput(name.string()).string(),
14062675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                        ResTable::normalizeForOutput(publicKey.string()).string());
1407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1410ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                } else if (depth == 3) {
1411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    withinActivity = false;
1412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    withinReceiver = false;
1413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    withinService = false;
14149d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                    withinProvider = false;
1415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasIntentFilter = false;
141694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    hasMetaHostPaymentCategory = false;
141794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    hasMetaOffHostPaymentCategory = false;
141894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    hasBindDeviceAdminPermission = false;
141994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    hasBindInputMethodPermission = false;
142094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    hasBindAccessibilityServicePermission = false;
142194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    hasBindPrintServicePermission = false;
142294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    hasBindNfcServicePermission = false;
14239d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                    hasRequiredSafAttributes = false;
14249d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                    hasBindNotificationListenerServicePermission = false;
1425eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock                    hasBindDreamServicePermission = false;
1426ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                    if (withinApplication) {
1427ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        if(tag == "activity") {
1428ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            withinActivity = true;
1429ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            activityName = AaptXml::getAttribute(tree, NAME_ATTR, &error);
1430ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (error != "") {
1431ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1432ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        error.string());
1433ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                goto bail;
1434ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
1435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1436ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            activityLabel = AaptXml::getResolvedAttribute(res, tree, LABEL_ATTR,
1437ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    &error);
1438ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (error != "") {
1439ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                fprintf(stderr, "ERROR getting 'android:label' attribute: %s\n",
1440ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        error.string());
1441ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                goto bail;
1442ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
1443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1444ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            activityIcon = AaptXml::getResolvedAttribute(res, tree, ICON_ATTR,
1445ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    &error);
1446ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (error != "") {
1447ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n",
1448ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        error.string());
1449ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                goto bail;
1450ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
1451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1452ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            activityBanner = AaptXml::getResolvedAttribute(res, tree, BANNER_ATTR,
1453ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    &error);
14540a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                            if (error != "") {
14550a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                fprintf(stderr, "ERROR getting 'android:banner' attribute: %s\n",
14560a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                        error.string());
14570a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                goto bail;
14580a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                            }
14590a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn
1460ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            int32_t orien = AaptXml::getResolvedIntegerAttribute(res, tree,
1461ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                    SCREEN_ORIENTATION_ATTR, &error);
1462ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (error == "") {
1463ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                if (orien == 0 || orien == 6 || orien == 8) {
1464ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                    // Requests landscape, sensorLandscape, or reverseLandscape.
14652c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                    addImpliedFeature(&impliedFeatures, "android.hardware.screen.landscape",
14662c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                            "one or more activities have specified a landscape orientation");
1467ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                } else if (orien == 1 || orien == 7 || orien == 9) {
1468ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                    // Requests portrait, sensorPortrait, or reversePortrait.
14692c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                    addImpliedFeature(&impliedFeatures, "android.hardware.screen.portrait",
14702c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                            "one or more activities have specified a portrait orientation");
1471ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                }
1472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1473ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        } else if (tag == "uses-library") {
1474ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            String8 libraryName = AaptXml::getAttribute(tree, NAME_ATTR, &error);
1475ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (error != "") {
1476ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                fprintf(stderr,
1477ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        "ERROR getting 'android:name' attribute for uses-library"
1478ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        " %s\n", error.string());
1479ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                goto bail;
1480ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
1481ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            int req = AaptXml::getIntegerAttribute(tree,
1482ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    REQUIRED_ATTR, 1);
1483ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            printf("uses-library%s:'%s'\n",
14842675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                    req ? "" : "-not-required", ResTable::normalizeForOutput(
14852675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                            libraryName.string()).string());
1486ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        } else if (tag == "receiver") {
1487ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            withinReceiver = true;
1488ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            receiverName = AaptXml::getAttribute(tree, NAME_ATTR, &error);
1489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1490ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (error != "") {
1491ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                fprintf(stderr,
1492ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        "ERROR getting 'android:name' attribute for receiver:"
1493ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        " %s\n", error.string());
1494ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                goto bail;
1495ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
1496a5018c900f126ee8424c82497f32983873db741bAdam Lesinski
1497ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            String8 permission = AaptXml::getAttribute(tree, PERMISSION_ATTR,
1498ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    &error);
1499a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            if (error == "") {
1500a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                if (permission == "android.permission.BIND_DEVICE_ADMIN") {
1501a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                    hasBindDeviceAdminPermission = true;
1502a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                }
1503a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            } else {
1504a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                fprintf(stderr, "ERROR getting 'android:permission' attribute for"
1505a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                        " receiver '%s': %s\n", receiverName.string(), error.string());
1506a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            }
1507ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        } else if (tag == "service") {
1508ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            withinService = true;
1509ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            serviceName = AaptXml::getAttribute(tree, NAME_ATTR, &error);
1510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1511ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (error != "") {
1512ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                fprintf(stderr, "ERROR getting 'android:name' attribute for "
1513ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        "service:%s\n", error.string());
1514ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                goto bail;
1515ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
1516a5018c900f126ee8424c82497f32983873db741bAdam Lesinski
1517ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            String8 permission = AaptXml::getAttribute(tree, PERMISSION_ATTR,
1518ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    &error);
1519a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            if (error == "") {
1520a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                if (permission == "android.permission.BIND_INPUT_METHOD") {
1521a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                    hasBindInputMethodPermission = true;
1522a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                } else if (permission == "android.permission.BIND_ACCESSIBILITY_SERVICE") {
1523a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                    hasBindAccessibilityServicePermission = true;
1524a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                } else if (permission == "android.permission.BIND_PRINT_SERVICE") {
1525a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                    hasBindPrintServicePermission = true;
152694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                } else if (permission == "android.permission.BIND_NFC_SERVICE") {
152794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                    hasBindNfcServicePermission = true;
15289d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                } else if (permission == "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE") {
15299d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                    hasBindNotificationListenerServicePermission = true;
1530eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock                                } else if (permission == "android.permission.BIND_DREAM_SERVICE") {
1531eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock                                    hasBindDreamServicePermission = true;
1532a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                }
1533a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            } else {
1534a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                fprintf(stderr, "ERROR getting 'android:permission' attribute for"
1535a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                        " service '%s': %s\n", serviceName.string(), error.string());
1536a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            }
15379d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                        } else if (tag == "provider") {
15389d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            withinProvider = true;
15399d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski
1540ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            bool exported = AaptXml::getResolvedIntegerAttribute(res, tree,
1541ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    EXPORTED_ATTR, &error);
15429d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            if (error != "") {
15439d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                fprintf(stderr, "ERROR getting 'android:exported' attribute for provider:"
15449d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                        " %s\n", error.string());
15459d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                goto bail;
15469d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            }
15479d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski
1548ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            bool grantUriPermissions = AaptXml::getResolvedIntegerAttribute(
1549ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    res, tree, GRANT_URI_PERMISSIONS_ATTR, &error);
15509d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            if (error != "") {
15519d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                fprintf(stderr, "ERROR getting 'android:grantUriPermissions' attribute for provider:"
15529d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                        " %s\n", error.string());
15539d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                goto bail;
15549d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            }
15559d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski
1556ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            String8 permission = AaptXml::getResolvedAttribute(res, tree,
1557ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    PERMISSION_ATTR, &error);
15589d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            if (error != "") {
15599d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                fprintf(stderr, "ERROR getting 'android:permission' attribute for provider:"
15609d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                        " %s\n", error.string());
15619d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                goto bail;
15629d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            }
15639d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski
15649d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            hasRequiredSafAttributes |= exported && grantUriPermissions &&
15659d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                permission == "android.permission.MANAGE_DOCUMENTS";
15669d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski
1567ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        } else if (bundle->getIncludeMetaData() && tag == "meta-data") {
1568ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            String8 metaDataName = AaptXml::getResolvedAttribute(res, tree,
1569ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    NAME_ATTR, &error);
1570ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (error != "") {
1571ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                fprintf(stderr, "ERROR getting 'android:name' attribute for "
1572ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        "meta-data:%s\n", error.string());
1573ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                goto bail;
1574ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
15752675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            printf("meta-data: name='%s' ",
15762675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                    ResTable::normalizeForOutput(metaDataName.string()).string());
1577ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            printResolvedResourceAttribute(res, tree, VALUE_ATTR, String8("value"),
157876327314d2238e105f8b94909f9c0cf85caca318Maurice Chu                                    &error);
1579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (error != "") {
158076327314d2238e105f8b94909f9c0cf85caca318Maurice Chu                                // Try looking for a RESOURCE_ATTR
158176327314d2238e105f8b94909f9c0cf85caca318Maurice Chu                                error = "";
1582ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                printResolvedResourceAttribute(res, tree, RESOURCE_ATTR,
158376327314d2238e105f8b94909f9c0cf85caca318Maurice Chu                                        String8("resource"), &error);
1584ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                if (error != "") {
158576327314d2238e105f8b94909f9c0cf85caca318Maurice Chu                                    fprintf(stderr, "ERROR getting 'android:value' or "
158676327314d2238e105f8b94909f9c0cf85caca318Maurice Chu                                            "'android:resource' attribute for "
158776327314d2238e105f8b94909f9c0cf85caca318Maurice Chu                                            "meta-data:%s\n", error.string());
1588ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                    goto bail;
1589ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                }
1590ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
159176327314d2238e105f8b94909f9c0cf85caca318Maurice Chu                            printf("\n");
1592ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        } else if (withinSupportsInput && tag == "input-type") {
1593ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
1594ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (name != "" && error == "") {
1595ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                supportedInput.add(name);
1596ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            } else {
1597ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1598ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        error.string());
1599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                goto bail;
1600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
16022c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                    } else if (withinFeatureGroup && tag == "uses-feature") {
1603d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                        FeatureGroup& top = featureGroups.editTop();
1604d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski
1605ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        String8 name = AaptXml::getResolvedAttribute(res, tree, NAME_ATTR, &error);
1606d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                        if (name != "" && error == "") {
1607d3edfde51bd069a63e820282421d1a534fcf00ceAdam Lesinski                            top.features.add(name, true);
1608d3edfde51bd069a63e820282421d1a534fcf00ceAdam Lesinski                            addParentFeatures(&top, name);
1609d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                        } else {
1610ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            int vers = AaptXml::getIntegerAttribute(tree, GL_ES_VERSION_ATTR,
1611ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    &error);
1612d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                            if (error == "") {
1613d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                                if (vers > top.openGLESVersion) {
1614d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                                    top.openGLESVersion = vers;
1615d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                                }
1616d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                            }
16172c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                        }
1618a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                    }
161994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                } else if (depth == 4) {
162094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    if (tag == "intent-filter") {
162194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        hasIntentFilter = true;
162294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        withinIntentFilter = true;
162394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actMainActivity = false;
162494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actWidgetReceivers = false;
162594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actImeService = false;
162694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actWallpaperService = false;
162794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actAccessibilityService = false;
162894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actPrintService = false;
162994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actDeviceAdminEnabled = false;
163094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actHostApduService = false;
163194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actOffHostApduService = false;
16329d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                        actDocumentsProvider = false;
16339d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                        actNotificationListenerService = false;
1634eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock                        actDreamService = false;
16359d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                        actCamera = false;
16369d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                        actCameraSecure = false;
16379d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                        catLauncher = false;
163894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    } else if (withinService && tag == "meta-data") {
1639ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
164094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        if (error != "") {
164194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            fprintf(stderr, "ERROR getting 'android:name' attribute for"
164294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                    " meta-data tag in service '%s': %s\n", serviceName.string(), error.string());
164394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            goto bail;
164494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        }
164594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
164694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        if (name == "android.nfc.cardemulation.host_apdu_service" ||
164794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                name == "android.nfc.cardemulation.off_host_apdu_service") {
164894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            bool offHost = true;
164994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            if (name == "android.nfc.cardemulation.host_apdu_service") {
165094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                offHost = false;
165194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            }
165294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
1653ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            String8 xmlPath = AaptXml::getResolvedAttribute(res, tree,
1654ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    RESOURCE_ATTR, &error);
165594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            if (error != "") {
165694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                fprintf(stderr, "ERROR getting 'android:resource' attribute for"
165794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                        " meta-data tag in service '%s': %s\n", serviceName.string(), error.string());
165894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                goto bail;
165994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            }
166094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
166194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            Vector<String8> categories = getNfcAidCategories(assets, xmlPath,
166294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                    offHost, &error);
166394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            if (error != "") {
166494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                fprintf(stderr, "ERROR getting AID category for service '%s'\n",
166594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                        serviceName.string());
166694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                goto bail;
166794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            }
166894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
166994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            const size_t catLen = categories.size();
167094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            for (size_t i = 0; i < catLen; i++) {
167194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                bool paymentCategory = (categories[i] == "payment");
167294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                if (offHost) {
167394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                    hasMetaOffHostPaymentCategory |= paymentCategory;
167494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                } else {
167594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                    hasMetaHostPaymentCategory |= paymentCategory;
167694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                }
167794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            }
167894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        }
167994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    }
1680a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                } else if ((depth == 5) && withinIntentFilter) {
1681a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                    String8 action;
1682a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                    if (tag == "action") {
1683ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        action = AaptXml::getAttribute(tree, NAME_ATTR, &error);
1684a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        if (error != "") {
1685a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1686a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                    error.string());
1687a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            goto bail;
1688a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        }
1689a5018c900f126ee8424c82497f32983873db741bAdam Lesinski
1690a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        if (withinActivity) {
1691a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            if (action == "android.intent.action.MAIN") {
1692a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                isMainActivity = true;
1693a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                actMainActivity = true;
16949d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            } else if (action == "android.media.action.STILL_IMAGE_CAMERA" ||
16959d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                    action == "android.media.action.VIDEO_CAMERA") {
16969d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                actCamera = true;
16979d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            } else if (action == "android.media.action.STILL_IMAGE_CAMERA_SECURE") {
16989d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                actCameraSecure = true;
1699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1700a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        } else if (withinReceiver) {
1701a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            if (action == "android.appwidget.action.APPWIDGET_UPDATE") {
1702a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                actWidgetReceivers = true;
1703a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            } else if (action == "android.app.action.DEVICE_ADMIN_ENABLED") {
1704a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                actDeviceAdminEnabled = true;
1705282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1706a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        } else if (withinService) {
1707a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            if (action == "android.view.InputMethod") {
1708a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                actImeService = true;
1709a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            } else if (action == "android.service.wallpaper.WallpaperService") {
1710a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                actWallpaperService = true;
1711a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            } else if (action == "android.accessibilityservice.AccessibilityService") {
1712a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                actAccessibilityService = true;
1713a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            } else if (action == "android.printservice.PrintService") {
1714a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                actPrintService = true;
171594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            } else if (action == "android.nfc.cardemulation.action.HOST_APDU_SERVICE") {
171694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                actHostApduService = true;
171794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            } else if (action == "android.nfc.cardemulation.action.OFF_HOST_APDU_SERVICE") {
171894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                actOffHostApduService = true;
17199d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            } else if (action == "android.service.notification.NotificationListenerService") {
17209d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                actNotificationListenerService = true;
1721eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock                            } else if (action == "android.service.dreams.DreamService") {
1722eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock                                actDreamService = true;
17239d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            }
17249d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                        } else if (withinProvider) {
17259d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            if (action == "android.content.action.DOCUMENTS_PROVIDER") {
17269d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                actDocumentsProvider = true;
1727282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1728282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1729a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        if (action == "android.intent.action.SEARCH") {
1730a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            isSearchable = true;
1731a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        }
1732a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                    }
1733282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1734a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                    if (tag == "category") {
1735ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        String8 category = AaptXml::getAttribute(tree, NAME_ATTR, &error);
1736a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        if (error != "") {
1737a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            fprintf(stderr, "ERROR getting 'name' attribute: %s\n",
1738a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                    error.string());
1739a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            goto bail;
1740a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        }
1741a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        if (withinActivity) {
1742a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            if (category == "android.intent.category.LAUNCHER") {
1743a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                isLauncherActivity = true;
17440a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                            } else if (category == "android.intent.category.LEANBACK_LAUNCHER") {
17450a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                isLeanbackLauncherActivity = true;
17469d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            } else if (category == "android.intent.category.HOME") {
17479d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                catLauncher = true;
1748282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1749282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1751282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1752282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1753282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1754282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Pre-1.6 implicitly granted permission compatibility logic
1755282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (targetSdk < 4) {
1756282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!hasWriteExternalStoragePermission) {
175758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesPermission(String8("android.permission.WRITE_EXTERNAL_STORAGE"));
175858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesImpliedPermission(String8("android.permission.WRITE_EXTERNAL_STORAGE"),
175958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                            String8("targetSdkVersion < 4"));
1760282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasWriteExternalStoragePermission = true;
1761282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1762282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!hasReadPhoneStatePermission) {
176358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesPermission(String8("android.permission.READ_PHONE_STATE"));
176458f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesImpliedPermission(String8("android.permission.READ_PHONE_STATE"),
176558f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                            String8("targetSdkVersion < 4"));
1766282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1767282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1768282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1769282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // If the application has requested WRITE_EXTERNAL_STORAGE, we will
1770282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // force them to always take READ_EXTERNAL_STORAGE as well.  We always
1771282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // do this (regardless of target API version) because we can't have
1772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // an app with write permission but not read permission.
1773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!hasReadExternalStoragePermission && hasWriteExternalStoragePermission) {
177458f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                printUsesPermission(String8("android.permission.READ_EXTERNAL_STORAGE"));
177558f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                printUsesImpliedPermission(String8("android.permission.READ_EXTERNAL_STORAGE"),
177658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                        String8("requested WRITE_EXTERNAL_STORAGE"));
1777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Pre-JellyBean call log permission compatibility.
1780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (targetSdk < 16) {
1781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!hasReadCallLogPermission && hasReadContactsPermission) {
178258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesPermission(String8("android.permission.READ_CALL_LOG"));
178358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesImpliedPermission(String8("android.permission.READ_CALL_LOG"),
178458f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                            String8("targetSdkVersion < 16 and requested READ_CONTACTS"));
1785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!hasWriteCallLogPermission && hasWriteContactsPermission) {
178758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesPermission(String8("android.permission.WRITE_CALL_LOG"));
178858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesImpliedPermission(String8("android.permission.WRITE_CALL_LOG"),
178958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                            String8("targetSdkVersion < 16 and requested WRITE_CONTACTS"));
1790282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1791282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1792282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
17932c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski            addImpliedFeature(&impliedFeatures, "android.hardware.touchscreen",
17942c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                    "default feature for all apps");
17952c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
17962c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski            const size_t numFeatureGroups = featureGroups.size();
17972c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski            if (numFeatureGroups == 0) {
17982c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                // If no <feature-group> tags were defined, apply auto-implied features.
17992c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                printFeatureGroup(commonFeatures, &impliedFeatures);
18002c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
18012c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski            } else {
18022c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                // <feature-group> tags are defined, so we ignore implied features and
18032c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                for (size_t i = 0; i < numFeatureGroups; i++) {
18042c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                    FeatureGroup& grp = featureGroups.editItemAt(i);
18052c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
1806d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                    if (commonFeatures.openGLESVersion > grp.openGLESVersion) {
1807d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                        grp.openGLESVersion = commonFeatures.openGLESVersion;
1808d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                    }
1809d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski
18102c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                    // Merge the features defined in the top level (not inside a <feature-group>)
18112c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                    // with this feature group.
18122c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                    const size_t numCommonFeatures = commonFeatures.features.size();
18132c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                    for (size_t j = 0; j < numCommonFeatures; j++) {
18142c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                        if (grp.features.indexOfKey(commonFeatures.features.keyAt(j)) < 0) {
1815d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                            grp.features.add(commonFeatures.features.keyAt(j),
1816d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                                    commonFeatures.features[j]);
18172c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                        }
1818282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1819282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
18202c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                   if (!grp.features.isEmpty()) {
18212c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                        printFeatureGroup(grp);
18222c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                    }
1823282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1824282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1825282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
18262c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
1827282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (hasWidgetReceivers) {
18289d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("app-widget");
1829282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1830a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            if (hasDeviceAdminReceiver) {
18319d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("device-admin");
1832a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            }
1833282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (hasImeService) {
18349d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("ime");
1835282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1836282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (hasWallpaperService) {
18379d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("wallpaper");
1838282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1839a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            if (hasAccessibilityService) {
18409d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("accessibility");
1841a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            }
1842a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            if (hasPrintService) {
18439d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("print-service");
1844a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            }
184594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            if (hasPaymentService) {
18469d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("payment");
18479d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            }
18489d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            if (isSearchable) {
18499d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("search");
18509d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            }
18519d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            if (hasDocumentsProvider) {
18529d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("document-provider");
18539d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            }
18549d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            if (hasLauncher) {
18559d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("launcher");
18569d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            }
18579d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            if (hasNotificationListenerService) {
18589d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("notification-listener");
18599d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            }
1860eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock            if (hasDreamService) {
1861eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock                printComponentPresence("dream");
1862eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock            }
18639d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            if (hasCameraActivity) {
18649d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("camera");
18659d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            }
18669d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            if (hasCameraSecureActivity) {
18679d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("camera-secure");
18689d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            }
18699d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski
18709d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            if (hasMainActivity) {
18719d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printf("main\n");
187294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            }
1873282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (hasOtherActivities) {
1874282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("other-activities\n");
1875282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
18769d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski             if (hasOtherReceivers) {
1877282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("other-receivers\n");
1878282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1879282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (hasOtherServices) {
1880282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("other-services\n");
1881282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1882282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1883282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // For modern apps, if screen size buckets haven't been specified
1884282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // but the new width ranges have, then infer the buckets from them.
1885282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (smallScreen > 0 && normalScreen > 0 && largeScreen > 0 && xlargeScreen > 0
1886282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    && requiresSmallestWidthDp > 0) {
1887282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                int compatWidth = compatibleWidthLimitDp;
1888282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (compatWidth <= 0) {
1889282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    compatWidth = requiresSmallestWidthDp;
1890282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1891282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (requiresSmallestWidthDp <= 240 && compatWidth >= 240) {
1892282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    smallScreen = -1;
1893282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1894282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    smallScreen = 0;
1895282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1896282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (requiresSmallestWidthDp <= 320 && compatWidth >= 320) {
1897282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    normalScreen = -1;
1898282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1899282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    normalScreen = 0;
1900282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1901282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (requiresSmallestWidthDp <= 480 && compatWidth >= 480) {
1902282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    largeScreen = -1;
1903282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1904282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    largeScreen = 0;
1905282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1906282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (requiresSmallestWidthDp <= 720 && compatWidth >= 720) {
1907282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    xlargeScreen = -1;
1908282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1909282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    xlargeScreen = 0;
1910282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1911282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1912282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1913282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Determine default values for any unspecified screen sizes,
1914282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // based on the target SDK of the package.  As of 4 (donut)
1915282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // the screen size support was introduced, so all default to
1916282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // enabled.
1917282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (smallScreen > 0) {
1918282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                smallScreen = targetSdk >= 4 ? -1 : 0;
1919282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1920282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (normalScreen > 0) {
1921282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                normalScreen = -1;
1922282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1923282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (largeScreen > 0) {
1924282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                largeScreen = targetSdk >= 4 ? -1 : 0;
1925282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1926282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (xlargeScreen > 0) {
1927282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Introduced in Gingerbread.
1928282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                xlargeScreen = targetSdk >= 9 ? -1 : 0;
1929282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1930282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (anyDensity > 0) {
1931282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                anyDensity = (targetSdk >= 4 || requiresSmallestWidthDp > 0
1932282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        || compatibleWidthLimitDp > 0) ? -1 : 0;
1933282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1934282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("supports-screens:");
1935282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (smallScreen != 0) {
1936282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf(" 'small'");
1937282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1938282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (normalScreen != 0) {
1939282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf(" 'normal'");
1940282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1941282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (largeScreen != 0) {
1942282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf(" 'large'");
1943282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1944282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (xlargeScreen != 0) {
1945282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf(" 'xlarge'");
1946282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1947282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("\n");
1948282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("supports-any-density: '%s'\n", anyDensity ? "true" : "false");
1949282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (requiresSmallestWidthDp > 0) {
1950282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("requires-smallest-width:'%d'\n", requiresSmallestWidthDp);
1951282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1952282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (compatibleWidthLimitDp > 0) {
1953282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("compatible-width-limit:'%d'\n", compatibleWidthLimitDp);
1954282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1955282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (largestWidthLimitDp > 0) {
1956282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("largest-width-limit:'%d'\n", largestWidthLimitDp);
1957282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1958282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1959282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("locales:");
1960282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t NL = locales.size();
1961282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t i=0; i<NL; i++) {
1962282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                const char* localeStr =  locales[i].string();
1963282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (localeStr == NULL || strlen(localeStr) == 0) {
1964282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    localeStr = "--_--";
1965282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1966282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf(" '%s'", localeStr);
1967282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1968282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("\n");
1969282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1970282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("densities:");
1971282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t ND = densities.size();
1972282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t i=0; i<ND; i++) {
1973282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf(" '%d'", densities[i]);
1974282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1975282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("\n");
1976282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1977282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            AssetDir* dir = assets.openNonAssetDir(assetsCookie, "lib");
1978282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (dir != NULL) {
1979282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (dir->getFileCount() > 0) {
1980e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                    SortedVector<String8> architectures;
1981282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    for (size_t i=0; i<dir->getFileCount(); i++) {
1982e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        architectures.add(ResTable::normalizeForOutput(
1983e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                                dir->getFileName(i).string()));
1984e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                    }
1985e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski
1986e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                    bool outputAltNativeCode = false;
1987e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                    // A multiArch package is one that contains 64-bit and
1988e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                    // 32-bit versions of native code and expects 3rd-party
1989e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                    // apps to load these native code libraries. Since most
1990e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                    // 64-bit systems also support 32-bit apps, the apps
1991e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                    // loading this multiArch package's code may be either
1992e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                    // 32-bit or 64-bit.
1993e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                    if (hasMultiArch) {
1994e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        // If this is a multiArch package, report the 64-bit
1995e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        // version only. Then as a separate entry, report the
1996e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        // rest.
1997e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        //
1998e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        // If we report the 32-bit architecture, this APK will
1999e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        // be installed on a 32-bit device, causing a large waste
2000e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        // of bandwidth and disk space. This assumes that
2001e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        // the developer of the multiArch package has also
2002e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        // made a version that is 32-bit only.
2003e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        String8 intel64("x86_64");
2004e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        String8 arm64("arm64-v8a");
2005e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        ssize_t index = architectures.indexOf(intel64);
2006e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        if (index < 0) {
2007e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                            index = architectures.indexOf(arm64);
2008e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        }
2009e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski
2010e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        if (index >= 0) {
2011e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                            printf("native-code: '%s'\n", architectures[index].string());
2012e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                            architectures.removeAt(index);
2013e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                            outputAltNativeCode = true;
2014e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        }
2015e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                    }
2016e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski
2017e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                    const size_t archCount = architectures.size();
2018e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                    if (archCount > 0) {
2019e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        if (outputAltNativeCode) {
2020e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                            printf("alt-");
2021e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        }
2022e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        printf("native-code:");
2023e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        for (size_t i = 0; i < archCount; i++) {
2024e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                            printf(" '%s'", architectures[i].string());
2025e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        }
2026e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        printf("\n");
2027282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2028282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2029282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                delete dir;
2030282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2031282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else if (strcmp("badger", option) == 0) {
2032282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("%s", CONSOLE_DATA);
2033282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else if (strcmp("configurations", option) == 0) {
2034282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Vector<ResTable_config> configs;
2035282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            res.getConfigurations(&configs);
2036282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t N = configs.size();
2037282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t i=0; i<N; i++) {
2038282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("%s\n", configs[i].toString().string());
2039282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2040282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
2041282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: unknown dump option '%s'\n", option);
2042282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
2043282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2044282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2045282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2046282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    result = NO_ERROR;
2047282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2048282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail:
2049282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (asset) {
2050282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        delete asset;
2051282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2052282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return (result != NO_ERROR);
2053282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2054282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2055282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2056282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
2057282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Handle the "add" command, which wants to add files to a new or
2058282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * pre-existing archive.
2059282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
2060282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doAdd(Bundle* bundle)
2061282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2062282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ZipFile* zip = NULL;
2063282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t result = UNKNOWN_ERROR;
2064282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char* zipFileName;
2065282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2066282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getUpdate()) {
2067282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        /* avoid confusion */
2068282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: can't use '-u' with add\n");
2069282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2070282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2071282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2072282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getFileSpecCount() < 1) {
2073282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: must specify zip file name\n");
2074282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2075282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2076282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    zipFileName = bundle->getFileSpecEntry(0);
2077282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2078282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getFileSpecCount() < 2) {
2079282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "NOTE: nothing to do\n");
2080282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2081282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2082282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2083282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    zip = openReadWrite(zipFileName, true);
2084282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (zip == NULL) {
2085282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: failed opening/creating '%s' as Zip file\n", zipFileName);
2086282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2087282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2088282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2089282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (int i = 1; i < bundle->getFileSpecCount(); i++) {
2090282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const char* fileName = bundle->getFileSpecEntry(i);
2091282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2092282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (strcasecmp(String8(fileName).getPathExtension().string(), ".gz") == 0) {
2093282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf(" '%s'... (from gzip)\n", fileName);
2094282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            result = zip->addGzip(fileName, String8(fileName).getBasePath().string(), NULL);
2095282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
2096282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (bundle->getJunkPath()) {
2097282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String8 storageName = String8(fileName).getPathLeaf();
20982675f769673f69b0661ddee346292f25cb30a296Maurice Chu                printf(" '%s' as '%s'...\n", fileName,
20992675f769673f69b0661ddee346292f25cb30a296Maurice Chu                        ResTable::normalizeForOutput(storageName.string()).string());
2100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                result = zip->add(fileName, storageName.string(),
2101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  bundle->getCompressionMethod(), NULL);
2102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
2103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf(" '%s'...\n", fileName);
2104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                result = zip->add(fileName, bundle->getCompressionMethod(), NULL);
2105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (result != NO_ERROR) {
2108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "Unable to add '%s' to '%s'", bundle->getFileSpecEntry(i), zipFileName);
2109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (result == NAME_NOT_FOUND) {
2110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, ": file not found\n");
2111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (result == ALREADY_EXISTS) {
2112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, ": already exists in archive\n");
2113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
2114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, "\n");
2115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
2117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    result = NO_ERROR;
2121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail:
2123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    delete zip;
2124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return (result != NO_ERROR);
2125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
2129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Delete files from an existing archive.
2130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
2131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doRemove(Bundle* bundle)
2132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ZipFile* zip = NULL;
2134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t result = UNKNOWN_ERROR;
2135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char* zipFileName;
2136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getFileSpecCount() < 1) {
2138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: must specify zip file name\n");
2139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    zipFileName = bundle->getFileSpecEntry(0);
2142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getFileSpecCount() < 2) {
2144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "NOTE: nothing to do\n");
2145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    zip = openReadWrite(zipFileName, false);
2149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (zip == NULL) {
2150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: failed opening Zip archive '%s'\n",
2151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            zipFileName);
2152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (int i = 1; i < bundle->getFileSpecCount(); i++) {
2156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const char* fileName = bundle->getFileSpecEntry(i);
2157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ZipEntry* entry;
2158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        entry = zip->getEntryByName(fileName);
2160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (entry == NULL) {
2161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf(" '%s' NOT FOUND\n", fileName);
2162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
2163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        result = zip->remove(entry);
2166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (result != NO_ERROR) {
2168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "Unable to delete '%s' from '%s'\n",
2169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                bundle->getFileSpecEntry(i), zipFileName);
2170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
2171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /* update the archive */
2175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    zip->flush();
2176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail:
2178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    delete zip;
2179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return (result != NO_ERROR);
2180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
21823921e87e6e67a063caa1987937d7944b24aef489Adam Lesinskistatic status_t addResourcesToBuilder(const sp<AaptDir>& dir, const sp<ApkBuilder>& builder, bool ignoreConfig=false) {
2183fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    const size_t numDirs = dir->getDirs().size();
2184fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    for (size_t i = 0; i < numDirs; i++) {
21853921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski        bool ignore = ignoreConfig;
21863921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski        const sp<AaptDir>& subDir = dir->getDirs().valueAt(i);
21873921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski        const char* dirStr = subDir->getLeaf().string();
21883921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski        if (!ignore && strstr(dirStr, "mipmap") == dirStr) {
21893921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski            ignore = true;
21903921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski        }
21913921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski        status_t err = addResourcesToBuilder(subDir, builder, ignore);
2192fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        if (err != NO_ERROR) {
2193fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            return err;
2194fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        }
2195fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    }
2196fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski
2197fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    const size_t numFiles = dir->getFiles().size();
2198fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    for (size_t i = 0; i < numFiles; i++) {
2199fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        sp<AaptGroup> gp = dir->getFiles().valueAt(i);
2200fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        const size_t numConfigs = gp->getFiles().size();
2201fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        for (size_t j = 0; j < numConfigs; j++) {
22023921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski            status_t err = NO_ERROR;
22033921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski            if (ignoreConfig) {
22043921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski                err = builder->getBaseSplit()->addEntry(gp->getPath(), gp->getFiles().valueAt(j));
22053921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski            } else {
22063921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski                err = builder->addEntry(gp->getPath(), gp->getFiles().valueAt(j));
22073921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski            }
2208fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            if (err != NO_ERROR) {
2209fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                fprintf(stderr, "Failed to add %s (%s) to builder.\n",
2210fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                        gp->getPath().string(), gp->getFiles()[j]->getPrintableSource().string());
2211fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                return err;
2212fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            }
2213fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        }
2214fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    }
2215fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    return NO_ERROR;
2216fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski}
2217fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski
2218fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinskistatic String8 buildApkName(const String8& original, const sp<ApkSplit>& split) {
2219fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (split->isBase()) {
2220fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        return original;
2221fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    }
2222fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski
2223fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    String8 ext(original.getPathExtension());
2224fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (ext == String8(".apk")) {
2225fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        return String8::format("%s_%s%s",
2226fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                original.getBasePath().string(),
2227fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                split->getDirectorySafeName().string(),
2228fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                ext.string());
2229fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    }
2230fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski
2231fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    return String8::format("%s_%s", original.string(),
2232fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            split->getDirectorySafeName().string());
2233fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski}
2234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
2236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Package up an asset directory and associated application files.
2237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
2238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doPackage(Bundle* bundle)
2239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char* outputAPKFile;
2241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int retVal = 1;
2242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err;
2243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<AaptAssets> assets;
2244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int N;
2245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    FILE* fp;
2246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String8 dependencyFile;
2247fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    sp<ApkBuilder> builder;
2248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2249a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin    // -c en_XA or/and ar_XB means do pseudolocalization
2250fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    sp<WeakResourceFilter> configFilter = new WeakResourceFilter();
2251fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    err = configFilter->parse(bundle->getConfigurations());
2252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
2253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2255fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (configFilter->containsPseudo()) {
2256a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        bundle->setPseudolocalize(bundle->getPseudolocalize() | PSEUDO_ACCENTED);
2257a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin    }
2258fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (configFilter->containsPseudoBidi()) {
2259a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        bundle->setPseudolocalize(bundle->getPseudolocalize() | PSEUDO_BIDI);
2260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    N = bundle->getFileSpecCount();
2263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (N < 1 && bundle->getResourceSourceDirs().size() == 0 && bundle->getJarFiles().size() == 0
226409384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski            && bundle->getAndroidManifestFile() == NULL && bundle->getAssetSourceDirs().size() == 0) {
2265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: no input files\n");
2266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    outputAPKFile = bundle->getOutputAPKFile();
2270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Make sure the filenames provided exist and are of the appropriate type.
2272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (outputAPKFile) {
2273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        FileType type;
2274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        type = getFileType(outputAPKFile);
2275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (type != kFileTypeNonexistent && type != kFileTypeRegular) {
2276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr,
2277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                "ERROR: output file '%s' exists but is not regular file\n",
2278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                outputAPKFile);
2279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
2280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Load the assets.
2284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    assets = new AaptAssets();
2285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Set up the resource gathering in assets if we're going to generate
2287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // dependency files. Every time we encounter a resource while slurping
2288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // the tree, we'll add it to these stores so we have full resource paths
2289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // to write to a dependency file.
2290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getGenDependencies()) {
2291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<FilePathStore> resPathStore = new FilePathStore;
2292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        assets->setFullResPaths(resPathStore);
2293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<FilePathStore> assetPathStore = new FilePathStore;
2294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        assets->setFullAssetPaths(assetPathStore);
2295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    err = assets->slurpFromArgs(bundle);
2298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err < 0) {
2299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getVerbose()) {
2303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        assets->print(String8());
2304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2306fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    // Create the ApkBuilder, which will collect the compiled files
2307fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    // to write to the final APK (or sets of APKs if we are building
2308fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    // a Split APK.
2309fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    builder = new ApkBuilder(configFilter);
2310fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski
2311fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    // If we are generating a Split APK, find out which configurations to split on.
2312fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (bundle->getSplitConfigurations().size() > 0) {
2313fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        const Vector<String8>& splitStrs = bundle->getSplitConfigurations();
2314fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        const size_t numSplits = splitStrs.size();
2315fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        for (size_t i = 0; i < numSplits; i++) {
2316fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            std::set<ConfigDescription> configs;
2317fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            if (!AaptConfig::parseCommaSeparatedList(splitStrs[i], &configs)) {
2318fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                fprintf(stderr, "ERROR: failed to parse split configuration '%s'\n", splitStrs[i].string());
2319fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                goto bail;
2320fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            }
2321fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski
2322fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            err = builder->createSplitForConfigs(configs);
2323fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            if (err != NO_ERROR) {
2324fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                goto bail;
2325fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            }
2326fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        }
2327fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    }
2328fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski
2329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // If they asked for any fileAs that need to be compiled, do so.
2330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getResourceSourceDirs().size() || bundle->getAndroidManifestFile()) {
2331fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        err = buildResources(bundle, assets, builder);
2332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != 0) {
2333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
2334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // At this point we've read everything and processed everything.  From here
2338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // on out it's just writing output files.
2339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (SourcePos::hasErrors()) {
2340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Update symbols with information about which ones are needed as Java symbols.
2344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    assets->applyJavaSymbols();
2345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (SourcePos::hasErrors()) {
2346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // If we've been asked to generate a dependency file, do that here
2350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getGenDependencies()) {
2351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // If this is the packaging step, generate the dependency file next to
2352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // the output apk (e.g. bin/resources.ap_.d)
2353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (outputAPKFile) {
2354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            dependencyFile = String8(outputAPKFile);
2355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Add the .d extension to the dependency file.
2356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            dependencyFile.append(".d");
2357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
2358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Else if this is the R.java dependency generation step,
2359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // generate the dependency file in the R.java package subdirectory
2360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // e.g. gen/com/foo/app/R.java.d
2361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            dependencyFile = String8(bundle->getRClassDir());
2362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            dependencyFile.appendPath("R.java.d");
2363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Make sure we have a clean dependency file to start with
2365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fp = fopen(dependencyFile, "w");
2366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fclose(fp);
2367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Write out R.java constants
2370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (!assets->havePrivateSymbols()) {
2371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (bundle->getCustomPackage() == NULL) {
2372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Write the R.java file into the appropriate class directory
2373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // e.g. gen/com/foo/app/R.java
23741e466385d4a4f1acee080fa0fdf16cc8fd8ce7caAdam Lesinski            err = writeResourceSymbols(bundle, assets, assets->getPackage(), true,
23751e466385d4a4f1acee080fa0fdf16cc8fd8ce7caAdam Lesinski                    bundle->getBuildSharedLibrary());
2376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
2377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const String8 customPkg(bundle->getCustomPackage());
23781e466385d4a4f1acee080fa0fdf16cc8fd8ce7caAdam Lesinski            err = writeResourceSymbols(bundle, assets, customPkg, true,
23791e466385d4a4f1acee080fa0fdf16cc8fd8ce7caAdam Lesinski                    bundle->getBuildSharedLibrary());
2380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err < 0) {
2382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
2383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // If we have library files, we're going to write our R.java file into
2385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // the appropriate class directory for those libraries as well.
2386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // e.g. gen/com/foo/app/lib/R.java
2387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (bundle->getExtraPackages() != NULL) {
2388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Split on colon
2389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 libs(bundle->getExtraPackages());
2390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            char* packageString = strtok(libs.lockBuffer(libs.length()), ":");
2391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            while (packageString != NULL) {
2392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Write the R.java file out with the correct package name
23931e466385d4a4f1acee080fa0fdf16cc8fd8ce7caAdam Lesinski                err = writeResourceSymbols(bundle, assets, String8(packageString), true, false);
2394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (err < 0) {
2395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    goto bail;
2396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2397282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                packageString = strtok(NULL, ":");
2398282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            libs.unlockBuffer();
2400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
24021e466385d4a4f1acee080fa0fdf16cc8fd8ce7caAdam Lesinski        err = writeResourceSymbols(bundle, assets, assets->getPackage(), false, false);
2403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err < 0) {
2404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
2405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
24061e466385d4a4f1acee080fa0fdf16cc8fd8ce7caAdam Lesinski        err = writeResourceSymbols(bundle, assets, assets->getSymbolsPrivatePackage(), true, false);
2407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err < 0) {
2408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
2409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Write out the ProGuard file
2413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    err = writeProguardFile(bundle, assets);
2414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err < 0) {
2415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Write the apk
2419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (outputAPKFile) {
2420fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        // Gather all resources and add them to the APK Builder. The builder will then
2421fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        // figure out which Split they belong in.
2422fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        err = addResourcesToBuilder(assets, builder);
2423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != NO_ERROR) {
2424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
2425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2426fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski
2427fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        const Vector<sp<ApkSplit> >& splits = builder->getSplits();
2428fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        const size_t numSplits = splits.size();
2429fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        for (size_t i = 0; i < numSplits; i++) {
2430fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            const sp<ApkSplit>& split = splits[i];
2431fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            String8 outputPath = buildApkName(String8(outputAPKFile), split);
2432fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            err = writeAPK(bundle, outputPath, split);
2433fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            if (err != NO_ERROR) {
2434fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                fprintf(stderr, "ERROR: packaging of '%s' failed\n", outputPath.string());
2435fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                goto bail;
2436fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            }
2437fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        }
2438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2440282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // If we've been asked to generate a dependency file, we need to finish up here.
2441282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // the writeResourceSymbols and writeAPK functions have already written the target
2442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // half of the dependency file, now we need to write the prerequisites. (files that
2443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // the R.java file or .ap_ file depend on)
2444282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getGenDependencies()) {
2445282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Now that writeResourceSymbols or writeAPK has taken care of writing
2446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // the targets to our dependency file, we'll write the prereqs
2447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fp = fopen(dependencyFile, "a+");
2448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(fp, " : ");
2449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        bool includeRaw = (outputAPKFile != NULL);
2450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        err = writeDependencyPreReqs(bundle, assets, fp, includeRaw);
2451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Also manually add the AndroidManifeset since it's not under res/ or assets/
2452282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // and therefore was not added to our pathstores during slurping
2453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(fp, "%s \\\n", bundle->getAndroidManifestFile());
2454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fclose(fp);
2455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    retVal = 0;
2458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail:
2459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (SourcePos::hasErrors()) {
2460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        SourcePos::printErrors(stderr);
2461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return retVal;
2463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
2466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Do PNG Crunching
2467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * PRECONDITIONS
2468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *  -S flag points to a source directory containing drawable* folders
2469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *  -C flag points to destination directory. The folder structure in the
2470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *     source directory will be mirrored to the destination (cache) directory
2471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
2472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * POSTCONDITIONS
2473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *  Destination directory will be updated to match the PNG files in
24742675f769673f69b0661ddee346292f25cb30a296Maurice Chu *  the source directory.
2475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
2476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doCrunch(Bundle* bundle)
2477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(stdout, "Crunching PNG Files in ");
2479282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(stdout, "source dir: %s\n", bundle->getResourceSourceDirs()[0]);
2480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(stdout, "To destination dir: %s\n", bundle->getCrunchedOutputDir());
2481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    updatePreProcessedCache(bundle);
2483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
2485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
2488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Do PNG Crunching on a single flag
2489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *  -i points to a single png file
2490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *  -o points to a single png output file
2491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
2492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doSingleCrunch(Bundle* bundle)
2493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(stdout, "Crunching single PNG file: %s\n", bundle->getSingleCrunchInputFile());
2495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(stdout, "\tOutput file: %s\n", bundle->getSingleCrunchOutputFile());
2496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String8 input(bundle->getSingleCrunchInputFile());
2498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String8 output(bundle->getSingleCrunchOutputFile());
2499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (preProcessImageToCache(bundle, input, output) != NO_ERROR) {
2501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // we can't return the status_t as it gets truncate to the lower 8 bits.
2502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return 42;
2503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2504282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
2506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2507282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2508282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskichar CONSOLE_DATA[2925] = {
2509282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 95, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2511282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2512282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32,
2513282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 63,
2514282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    86, 35, 40, 46, 46, 95, 95, 95, 95, 97, 97, 44, 32, 46, 124, 42, 33, 83,
2515282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    62, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2516282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2517282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 46, 58, 59, 61, 59, 61, 81,
2518282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 66, 96, 61, 61, 58, 46, 46, 46, 58, 32, 32, 32, 32, 32, 32,
2519282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32,
2520282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2521282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 46, 61, 59, 59, 59, 58, 106, 81, 81, 81, 81, 102, 59, 61, 59,
2522282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 61, 61, 61, 58, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2523282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2524282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59,
2525282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 58, 109, 81, 81, 81, 81, 61, 59, 59, 59, 59, 59, 58, 59, 59, 46, 32,
2526282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2527282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2528282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 60, 81, 81, 81, 81, 87,
2529282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    58, 59, 59, 59, 59, 59, 59, 61, 119, 44, 32, 32, 32, 32, 32, 32, 32, 32,
2530282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32,
2531282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46,
2532282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    47, 61, 59, 59, 58, 100, 81, 81, 81, 81, 35, 58, 59, 59, 59, 59, 59, 58,
2533282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    121, 81, 91, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2534282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2535282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 109, 58, 59, 59, 61, 81, 81,
2536282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 109, 58, 59, 59, 59, 59, 61, 109, 81, 81, 76, 46, 32, 32, 32,
2537282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32,
2538282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2539282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 41, 87, 59, 61, 59, 41, 81, 81, 81, 81, 81, 81, 59, 61, 59,
2540282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 58, 109, 81, 81, 87, 39, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2541282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2542282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 60, 81, 91, 59,
2543282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 61, 81, 81, 81, 81, 81, 87, 43, 59, 58, 59, 60, 81, 81, 81, 76, 32,
2544282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2545282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2546282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 52, 91, 58, 45, 59, 87, 81, 81, 81, 81,
2547282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    70, 58, 58, 58, 59, 106, 81, 81, 81, 91, 32, 32, 32, 32, 32, 32, 32, 32,
2548282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32,
2549282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2550282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 93, 40, 32, 46, 59, 100, 81, 81, 81, 81, 40, 58, 46, 46, 58, 100, 81,
2551282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 68, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2552282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 46, 46, 46, 32, 46, 46, 46, 32, 46, 32, 46, 45, 91, 59, 61, 58, 109,
2554282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 87, 46, 58, 61, 59, 60, 81, 81, 80, 32, 32, 32, 32, 32, 32,
2555282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32,
2556282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 46, 46, 61, 59, 61, 61, 61, 59, 61, 61, 59,
2557282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 58, 58, 46, 46, 41, 58, 59, 58, 81, 81, 81, 81, 69, 58, 59, 59,
2558282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    60, 81, 81, 68, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2559282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 58, 59,
2560282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    61, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 61, 46,
2561282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    61, 59, 93, 81, 81, 81, 81, 107, 58, 59, 58, 109, 87, 68, 96, 32, 32, 32,
2562282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2563282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 10, 32, 32, 32, 46, 60, 61, 61, 59, 59, 59, 59, 59, 59, 59, 59,
2564282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 59, 59, 59, 59, 58, 58, 58, 115, 109, 68, 41, 36, 81,
2565282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    109, 46, 61, 61, 81, 69, 96, 46, 58, 58, 46, 58, 46, 46, 32, 32, 32, 32,
2566282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 46, 32, 95, 81,
2567282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    67, 61, 61, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
2568282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 58, 68, 39, 61, 105, 61, 63, 81, 119, 58, 106, 80, 32, 58,
2569282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    61, 59, 59, 61, 59, 61, 59, 61, 46, 95, 32, 32, 32, 32, 32, 32, 32, 32,
2570282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 10, 32, 32, 36, 81, 109, 105, 59, 61, 59, 59, 59,
2571282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 46, 58, 37,
2572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    73, 108, 108, 62, 52, 81, 109, 34, 32, 61, 59, 59, 59, 59, 59, 59, 59, 59,
2573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 61, 59, 61, 61, 46, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10,
2574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 46, 45, 57, 101, 43, 43, 61, 61, 59, 59, 59, 59, 59, 59, 61, 59, 59,
2575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 59, 59, 58, 97, 46, 61, 108, 62, 126, 58, 106, 80, 96,
2576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    46, 61, 61, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 61,
2577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    97, 103, 97, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 45, 46, 32,
2578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    46, 32, 32, 32, 32, 32, 32, 32, 32, 45, 45, 45, 58, 59, 59, 59, 59, 61,
2579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    119, 81, 97, 124, 105, 124, 124, 39, 126, 95, 119, 58, 61, 58, 59, 59, 59,
2580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 119, 81, 81, 99, 32, 32,
2581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 58, 59, 59, 58, 106, 81, 81, 81, 109, 119,
2583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    119, 119, 109, 109, 81, 81, 122, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59,
2584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 58, 115, 81, 87, 81, 102, 32, 32, 32, 32, 32, 32, 10,
2585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 61, 58, 59, 61, 81, 81, 81, 81, 81, 81, 87, 87, 81, 81, 81, 81,
2587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 58, 59, 59, 59, 59, 59, 59, 59, 59, 58, 45, 45, 45, 59, 59, 59, 41,
2588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    87, 66, 33, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32,
2589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 59, 59, 93, 81,
2590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 40, 58, 59, 59, 59, 58,
2591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    45, 32, 46, 32, 32, 32, 32, 32, 46, 32, 126, 96, 32, 32, 32, 32, 32, 32,
2592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2593282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 58, 61, 59, 58, 81, 81, 81, 81, 81, 81, 81, 81,
2594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 81, 81, 40, 58, 59, 59, 59, 58, 32, 32, 32, 32, 32, 32, 32,
2595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32,
2596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58,
2597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 58, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 40, 58,
2598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 46, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 59, 60, 81, 81, 81, 81,
2601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 81, 81, 81, 81, 81, 81, 59, 61, 59, 59, 61, 32, 32, 32, 32,
2602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 58, 59, 59, 93, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
2605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 40, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32,
2607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 58, 106,
2608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 76, 58, 59, 59, 59,
2609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 61, 58, 58, 81, 81, 81, 81, 81, 81, 81, 81,
2612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 81, 81, 87, 58, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32,
2613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32,
2614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    58, 59, 61, 41, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 87, 59,
2616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    61, 58, 59, 59, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 58, 61, 81, 81, 81,
2619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 81, 81, 81, 81, 81, 81, 107, 58, 59, 59, 59, 59, 58, 32, 32,
2620282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 58, 59, 59, 58, 51, 81, 81, 81, 81, 81, 81, 81, 81, 81,
2623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 102, 94, 59, 59, 59, 59, 59, 61, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32,
2625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 59,
2626282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 43, 63, 36, 81, 81, 81, 87, 64, 86, 102, 58, 59, 59, 59, 59, 59,
2627282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2628282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2629282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 59, 59, 59, 59, 43, 33,
2630282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    58, 126, 126, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 32, 46, 32, 32,
2631282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32,
2632282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46,
2633282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    61, 59, 59, 59, 58, 45, 58, 61, 59, 58, 58, 58, 61, 59, 59, 59, 59, 59,
2634282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 59, 59, 58, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32,
2635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32,
2636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 59, 59, 58, 95,
2637282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 45, 61, 59, 61, 59, 59, 59, 59, 59, 59, 59, 45, 58, 59, 59, 59, 59,
2638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    61, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 58, 61, 59, 59, 59, 59, 59, 61, 59, 61, 46, 46, 32, 45, 45, 45,
2641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 58, 45, 45, 46, 58, 59, 59, 59, 59, 59, 59, 61, 46, 32, 32, 32, 32,
2642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32,
2643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 58, 59, 59, 59, 59,
2644282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 61, 59, 46, 32, 32, 46, 32, 46, 32, 58, 61, 59, 59,
2645282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 59, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 45, 59, 59, 59, 59, 59, 59, 59, 59, 58, 32,
2648282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59, 59, 58, 32,
2649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10,
2650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    46, 61, 59, 59, 59, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 61,
2652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    46, 61, 59, 59, 59, 59, 59, 59, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32,
2654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59,
2655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 32, 46, 61, 58, 59, 59, 59, 59,
2656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 58, 59, 59, 59, 59, 59, 59, 59, 59, 46, 46, 32, 32, 32,
2659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59, 59, 45, 32, 32, 32, 32, 32,
2660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32,
2661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 32, 45, 61,
2662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 58, 32, 46, 32, 32, 32, 32, 32, 32, 32, 58, 59, 59,
2663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 58, 45, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 45, 45, 45, 45, 32, 46, 32,
2666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 45, 61, 59, 58, 45, 45, 32, 32, 32,
2667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 46, 32, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10
2672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski  };
2673