Command.cpp revision 9d5b08ea8c1eef6658418b33090a6a8142d75208
1282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//
2282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// Copyright 2006 The Android Open Source Project
3282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//
4282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// Android Asset Packaging Tool main entry point.
5282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//
6fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski#include "ApkBuilder.h"
7282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "Main.h"
8282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "Bundle.h"
9282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "ResourceFilter.h"
10282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "ResourceTable.h"
11282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "Images.h"
12282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "XMLNode.h"
13282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
14282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <utils/Log.h>
15282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <utils/threads.h>
16282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <utils/List.h>
17282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <utils/Errors.h>
18282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
19282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <fcntl.h>
20282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <errno.h>
21282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
22282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiusing namespace android;
23282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
24282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
25282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Show version info.  All the cool kids do it.
26282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
27282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doVersion(Bundle* bundle)
28282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
29282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getFileSpecCount() != 0) {
30282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printf("(ignoring extra arguments)\n");
31282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
32282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    printf("Android Asset Packaging Tool, v0.2\n");
33282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
34282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return 0;
35282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
36282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
37282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
38282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
39282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Open the file read only.  The call fails if the file doesn't exist.
40282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
41282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Returns NULL on failure.
42282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
43282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiZipFile* openReadOnly(const char* fileName)
44282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
45282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ZipFile* zip;
46282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t result;
47282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
48282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    zip = new ZipFile;
49282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    result = zip->open(fileName, ZipFile::kOpenReadOnly);
50282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (result != NO_ERROR) {
51282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (result == NAME_NOT_FOUND) {
52282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: '%s' not found\n", fileName);
53282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else if (result == PERMISSION_DENIED) {
54282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: '%s' access denied\n", fileName);
55282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
56282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: failed opening '%s' as Zip file\n",
57282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fileName);
58282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
59282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        delete zip;
60282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NULL;
61282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
62282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
63282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return zip;
64282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
65282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
66282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
67282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Open the file read-write.  The file will be created if it doesn't
68282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * already exist and "okayToCreate" is set.
69282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
70282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Returns NULL on failure.
71282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
72282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiZipFile* openReadWrite(const char* fileName, bool okayToCreate)
73282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
74282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ZipFile* zip = NULL;
75282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t result;
76282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int flags;
77282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
78282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    flags = ZipFile::kOpenReadWrite;
79282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (okayToCreate) {
80282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        flags |= ZipFile::kOpenCreate;
81282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
82282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
83282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    zip = new ZipFile;
84282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    result = zip->open(fileName, flags);
85282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (result != NO_ERROR) {
86282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        delete zip;
87282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        zip = NULL;
88282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
89282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
90282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
91282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail:
92282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return zip;
93282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
94282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
95282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
96282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
97282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Return a short string describing the compression method.
98282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
99282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiconst char* compressionName(int method)
100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (method == ZipEntry::kCompressStored) {
102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return "Stored";
103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else if (method == ZipEntry::kCompressDeflated) {
104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return "Deflated";
105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return "Unknown";
107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Return the percent reduction in size (0% == no compression).
112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint calcPercent(long uncompressedLen, long compressedLen)
114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (!uncompressedLen) {
116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return 0;
117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return (int) (100.0 - (compressedLen * 100.0) / uncompressedLen + 0.5);
119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Handle the "list" command, which can be a simple file dump or
124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * a verbose listing.
125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * The verbose listing closely matches the output of the Info-ZIP "unzip"
127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * command.
128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doList(Bundle* bundle)
130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int result = 1;
132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ZipFile* zip = NULL;
133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const ZipEntry* entry;
134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    long totalUncLen, totalCompLen;
135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char* zipFileName;
136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getFileSpecCount() != 1) {
138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: specify zip file name (only)\n");
139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    zipFileName = bundle->getFileSpecEntry(0);
142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    zip = openReadOnly(zipFileName);
144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (zip == NULL) {
145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int count, i;
149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getVerbose()) {
151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printf("Archive:  %s\n", zipFileName);
152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printf(
153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            " Length   Method    Size  Ratio   Offset      Date  Time  CRC-32    Name\n");
154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printf(
155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            "--------  ------  ------- -----  -------      ----  ----  ------    ----\n");
156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    totalUncLen = totalCompLen = 0;
159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    count = zip->getNumEntries();
161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (i = 0; i < count; i++) {
162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        entry = zip->getEntryByIndex(i);
163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (bundle->getVerbose()) {
164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            char dateBuf[32];
165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            time_t when;
166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            when = entry->getModWhen();
168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            strftime(dateBuf, sizeof(dateBuf), "%m-%d-%y %H:%M",
169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                localtime(&when));
170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("%8ld  %-7.7s %7ld %3d%%  %8zd  %s  %08lx  %s\n",
172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                (long) entry->getUncompressedLen(),
173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                compressionName(entry->getCompressionMethod()),
174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                (long) entry->getCompressedLen(),
175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                calcPercent(entry->getUncompressedLen(),
176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            entry->getCompressedLen()),
177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                (size_t) entry->getLFHOffset(),
178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                dateBuf,
179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                entry->getCRC32(),
180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                entry->getFileName());
181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("%s\n", entry->getFileName());
183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        totalUncLen += entry->getUncompressedLen();
186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        totalCompLen += entry->getCompressedLen();
187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getVerbose()) {
190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printf(
191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        "--------          -------  ---                            -------\n");
192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printf("%8ld          %7ld  %2d%%                            %d files\n",
193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            totalUncLen,
194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            totalCompLen,
195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            calcPercent(totalUncLen, totalCompLen),
196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            zip->getNumEntries());
197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getAndroidList()) {
200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        AssetManager assets;
201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!assets.addAssetPath(String8(zipFileName), NULL)) {
202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: list -a failed because assets could not be loaded\n");
203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const ResTable& res = assets.getResources(false);
207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (&res == NULL) {
208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("\nNo resource table found.\n");
209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#ifndef HAVE_ANDROID_OS
211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("\nResource table:\n");
212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            res.print(false);
213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif
214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Asset* manifestAsset = assets.openNonAsset("AndroidManifest.xml",
217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                   Asset::ACCESS_BUFFER);
218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (manifestAsset == NULL) {
219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("\nNo AndroidManifest.xml found.\n");
220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("\nAndroid manifest:\n");
222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ResXMLTree tree;
223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            tree.setTo(manifestAsset->getBuffer(true),
224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       manifestAsset->getLength());
225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printXMLBlock(&tree);
226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        delete manifestAsset;
228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    result = 0;
231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail:
233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    delete zip;
234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return result;
235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic ssize_t indexOfAttribute(const ResXMLTree& tree, uint32_t attrRes)
238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t N = tree.getAttributeCount();
240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (size_t i=0; i<N; i++) {
241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (tree.getAttributeNameResID(i) == attrRes) {
242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return (ssize_t)i;
243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return -1;
246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
248282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiString8 getAttribute(const ResXMLTree& tree, const char* ns,
249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            const char* attr, String8* outError)
250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t idx = tree.indexOfAttribute(ns, attr);
252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (idx < 0) {
253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return String8();
254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Res_value value;
256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (value.dataType != Res_value::TYPE_STRING) {
258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (outError != NULL) {
259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                *outError = "attribute is not a string value";
260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return String8();
262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t len;
265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const uint16_t* str = tree.getAttributeStringValue(idx, &len);
266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return str ? String8(str, len) : String8();
267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic String8 getAttribute(const ResXMLTree& tree, uint32_t attrRes, String8* outError)
270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t idx = indexOfAttribute(tree, attrRes);
272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (idx < 0) {
273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return String8();
274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Res_value value;
276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (value.dataType != Res_value::TYPE_STRING) {
278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (outError != NULL) {
279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                *outError = "attribute is not a string value";
280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return String8();
282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t len;
285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const uint16_t* str = tree.getAttributeStringValue(idx, &len);
286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return str ? String8(str, len) : String8();
287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic int32_t getIntegerAttribute(const ResXMLTree& tree, uint32_t attrRes,
290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String8* outError, int32_t defValue = -1)
291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t idx = indexOfAttribute(tree, attrRes);
293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (idx < 0) {
294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return defValue;
295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Res_value value;
297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (value.dataType < Res_value::TYPE_FIRST_INT
299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                || value.dataType > Res_value::TYPE_LAST_INT) {
300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (outError != NULL) {
301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                *outError = "attribute is not an integer value";
302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return defValue;
304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return value.data;
307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic int32_t getResolvedIntegerAttribute(const ResTable* resTable, const ResXMLTree& tree,
310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        uint32_t attrRes, String8* outError, int32_t defValue = -1)
311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t idx = indexOfAttribute(tree, attrRes);
313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (idx < 0) {
314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return defValue;
315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Res_value value;
317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (value.dataType == Res_value::TYPE_REFERENCE) {
319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            resTable->resolveReference(&value, 0);
320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (value.dataType < Res_value::TYPE_FIRST_INT
322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                || value.dataType > Res_value::TYPE_LAST_INT) {
323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (outError != NULL) {
324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                *outError = "attribute is not an integer value";
325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return defValue;
327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return value.data;
330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic String8 getResolvedAttribute(const ResTable* resTable, const ResXMLTree& tree,
333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        uint32_t attrRes, String8* outError)
334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t idx = indexOfAttribute(tree, attrRes);
336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (idx < 0) {
337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return String8();
338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Res_value value;
340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (value.dataType == Res_value::TYPE_STRING) {
342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            size_t len;
343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const uint16_t* str = tree.getAttributeStringValue(idx, &len);
344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return str ? String8(str, len) : String8();
345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        resTable->resolveReference(&value, 0);
347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (value.dataType != Res_value::TYPE_STRING) {
348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (outError != NULL) {
349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                *outError = "attribute is not a string value";
350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return String8();
352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t len;
355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const Res_value* value2 = &value;
356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char16_t* str = const_cast<ResTable*>(resTable)->valueToString(value2, 0, NULL, &len);
357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return str ? String8(str, len) : String8();
358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic void getResolvedResourceAttribute(Res_value* value, const ResTable* resTable,
361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const ResXMLTree& tree, uint32_t attrRes, String8* outError)
362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t idx = indexOfAttribute(tree, attrRes);
364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (idx < 0) {
365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (outError != NULL) {
366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            *outError = "attribute could not be found";
367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return;
369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (tree.getAttributeValue(idx, value) != NO_ERROR) {
371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (value->dataType == Res_value::TYPE_REFERENCE) {
372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            resTable->resolveReference(value, 0);
373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // The attribute was found and was resolved if need be.
375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return;
376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (outError != NULL) {
378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        *outError = "error getting resolved resource attribute";
379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
38276327314d2238e105f8b94909f9c0cf85caca318Maurice Chustatic void printResolvedResourceAttribute(const ResTable* resTable, const ResXMLTree& tree,
38376327314d2238e105f8b94909f9c0cf85caca318Maurice Chu        uint32_t attrRes, String8 attrLabel, String8* outError)
38476327314d2238e105f8b94909f9c0cf85caca318Maurice Chu{
38576327314d2238e105f8b94909f9c0cf85caca318Maurice Chu    Res_value value;
38676327314d2238e105f8b94909f9c0cf85caca318Maurice Chu    getResolvedResourceAttribute(&value, resTable, tree, attrRes, outError);
38776327314d2238e105f8b94909f9c0cf85caca318Maurice Chu    if (*outError != "") {
38876327314d2238e105f8b94909f9c0cf85caca318Maurice Chu        *outError = "error print resolved resource attribute";
38976327314d2238e105f8b94909f9c0cf85caca318Maurice Chu        return;
39076327314d2238e105f8b94909f9c0cf85caca318Maurice Chu    }
39176327314d2238e105f8b94909f9c0cf85caca318Maurice Chu    if (value.dataType == Res_value::TYPE_STRING) {
39276327314d2238e105f8b94909f9c0cf85caca318Maurice Chu        String8 result = getResolvedAttribute(resTable, tree, attrRes, outError);
3932675f769673f69b0661ddee346292f25cb30a296Maurice Chu        printf("%s='%s'", attrLabel.string(),
3942675f769673f69b0661ddee346292f25cb30a296Maurice Chu                ResTable::normalizeForOutput(result.string()).string());
39576327314d2238e105f8b94909f9c0cf85caca318Maurice Chu    } else if (Res_value::TYPE_FIRST_INT <= value.dataType &&
39676327314d2238e105f8b94909f9c0cf85caca318Maurice Chu            value.dataType <= Res_value::TYPE_LAST_INT) {
39776327314d2238e105f8b94909f9c0cf85caca318Maurice Chu        printf("%s='%d'", attrLabel.string(), value.data);
39876327314d2238e105f8b94909f9c0cf85caca318Maurice Chu    } else {
39976327314d2238e105f8b94909f9c0cf85caca318Maurice Chu        printf("%s='0x%x'", attrLabel.string(), (int)value.data);
40076327314d2238e105f8b94909f9c0cf85caca318Maurice Chu    }
40176327314d2238e105f8b94909f9c0cf85caca318Maurice Chu}
40276327314d2238e105f8b94909f9c0cf85caca318Maurice Chu
403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// These are attribute resource constants for the platform, as found
404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// in android.R.attr
405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskienum {
406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    LABEL_ATTR = 0x01010001,
407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ICON_ATTR = 0x01010002,
408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    NAME_ATTR = 0x01010003,
409a5018c900f126ee8424c82497f32983873db741bAdam Lesinski    PERMISSION_ATTR = 0x01010006,
4109d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski    EXPORTED_ATTR = 0x01010010,
4119d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski    GRANT_URI_PERMISSIONS_ATTR = 0x0101001b,
41294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    RESOURCE_ATTR = 0x01010025,
413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    DEBUGGABLE_ATTR = 0x0101000f,
414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    VALUE_ATTR = 0x01010024,
415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    VERSION_CODE_ATTR = 0x0101021b,
416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    VERSION_NAME_ATTR = 0x0101021c,
417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    SCREEN_ORIENTATION_ATTR = 0x0101001e,
418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    MIN_SDK_VERSION_ATTR = 0x0101020c,
419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    MAX_SDK_VERSION_ATTR = 0x01010271,
420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    REQ_TOUCH_SCREEN_ATTR = 0x01010227,
421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    REQ_KEYBOARD_TYPE_ATTR = 0x01010228,
422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    REQ_HARD_KEYBOARD_ATTR = 0x01010229,
423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    REQ_NAVIGATION_ATTR = 0x0101022a,
424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    REQ_FIVE_WAY_NAV_ATTR = 0x01010232,
425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    TARGET_SDK_VERSION_ATTR = 0x01010270,
426282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    TEST_ONLY_ATTR = 0x01010272,
427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ANY_DENSITY_ATTR = 0x0101026c,
428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    GL_ES_VERSION_ATTR = 0x01010281,
429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    SMALL_SCREEN_ATTR = 0x01010284,
430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    NORMAL_SCREEN_ATTR = 0x01010285,
431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    LARGE_SCREEN_ATTR = 0x01010286,
432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    XLARGE_SCREEN_ATTR = 0x010102bf,
433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    REQUIRED_ATTR = 0x0101028e,
434282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    SCREEN_SIZE_ATTR = 0x010102ca,
435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    SCREEN_DENSITY_ATTR = 0x010102cb,
436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    REQUIRES_SMALLEST_WIDTH_DP_ATTR = 0x01010364,
437282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    COMPATIBLE_WIDTH_LIMIT_DP_ATTR = 0x01010365,
438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    LARGEST_WIDTH_LIMIT_DP_ATTR = 0x01010366,
439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    PUBLIC_KEY_ATTR = 0x010103a6,
44094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    CATEGORY_ATTR = 0x010103e8,
4410a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn    BANNER_ATTR = 0x10103f2,
442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski};
443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4442675f769673f69b0661ddee346292f25cb30a296Maurice ChuString8 getComponentName(String8 &pkgName, String8 &componentName) {
445282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t idx = componentName.find(".");
446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String8 retStr(pkgName);
447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (idx == 0) {
448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        retStr += componentName;
449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else if (idx < 0) {
450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        retStr += ".";
451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        retStr += componentName;
452282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
4532675f769673f69b0661ddee346292f25cb30a296Maurice Chu        return componentName;
454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
4552675f769673f69b0661ddee346292f25cb30a296Maurice Chu    return retStr;
456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4589cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinskistatic void printCompatibleScreens(ResXMLTree& tree, String8* outError) {
459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t len;
460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ResXMLTree::event_code_t code;
461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int depth = 0;
462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool first = true;
463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    printf("compatible-screens:");
464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (code == ResXMLTree::END_TAG) {
466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            depth--;
467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (depth < 0) {
468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                break;
469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (code != ResXMLTree::START_TAG) {
473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        depth++;
4769cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski        const char16_t* ctag16 = tree.getElementName(&len);
4779cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski        if (ctag16 == NULL) {
4789cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski            *outError = "failed to get XML element name (bad string pool)";
4799cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski            return;
4809cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski        }
4819cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski        String8 tag(ctag16);
482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (tag == "screen") {
483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int32_t screenSize = getIntegerAttribute(tree,
484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    SCREEN_SIZE_ATTR, NULL, -1);
485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int32_t screenDensity = getIntegerAttribute(tree,
486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    SCREEN_DENSITY_ATTR, NULL, -1);
487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (screenSize > 0 && screenDensity > 0) {
488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!first) {
489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    printf(",");
490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                first = false;
492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("'%d/%d'", screenSize, screenDensity);
493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    printf("\n");
497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
49958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinskistatic void printUsesPermission(const String8& name, bool optional=false, int maxSdkVersion=-1) {
50058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski    printf("uses-permission: name='%s'", ResTable::normalizeForOutput(name.string()).string());
50158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski    if (maxSdkVersion != -1) {
50258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski         printf(" maxSdkVersion='%d'", maxSdkVersion);
50358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski    }
50458f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski    printf("\n");
50558f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski
50658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski    if (optional) {
50758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski        printf("optional-permission: name='%s'",
50858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                ResTable::normalizeForOutput(name.string()).string());
50958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski        if (maxSdkVersion != -1) {
51058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski            printf(" maxSdkVersion='%d'", maxSdkVersion);
51158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski        }
51258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski        printf("\n");
51358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski    }
51458f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski}
51558f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski
51658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinskistatic void printUsesImpliedPermission(const String8& name, const String8& reason) {
51758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski    printf("uses-implied-permission: name='%s' reason='%s'\n",
51858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski            ResTable::normalizeForOutput(name.string()).string(),
51958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski            ResTable::normalizeForOutput(reason.string()).string());
52058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski}
52158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski
52294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam LesinskiVector<String8> getNfcAidCategories(AssetManager& assets, String8 xmlPath, bool offHost,
52394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski        String8 *outError = NULL)
52494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski{
52594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    Asset* aidAsset = assets.openNonAsset(xmlPath, Asset::ACCESS_BUFFER);
52694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    if (aidAsset == NULL) {
52794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski        if (outError != NULL) *outError = "xml resource does not exist";
52894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski        return Vector<String8>();
52994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    }
53094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
53194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    const String8 serviceTagName(offHost ? "offhost-apdu-service" : "host-apdu-service");
53294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
53394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    bool withinApduService = false;
53494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    Vector<String8> categories;
53594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
53694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    String8 error;
53794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    ResXMLTree tree;
53894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    tree.setTo(aidAsset->getBuffer(true), aidAsset->getLength());
53994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
54094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    size_t len;
54194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    int depth = 0;
54294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    ResXMLTree::event_code_t code;
54394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
54494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski        if (code == ResXMLTree::END_TAG) {
54594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            depth--;
5469cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski            const char16_t* ctag16 = tree.getElementName(&len);
5479cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski            if (ctag16 == NULL) {
5489cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                *outError = "failed to get XML element name (bad string pool)";
5499cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                return Vector<String8>();
5509cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski            }
5519cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski            String8 tag(ctag16);
55294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
55394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            if (depth == 0 && tag == serviceTagName) {
55494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                withinApduService = false;
55594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            }
55694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
55794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski        } else if (code == ResXMLTree::START_TAG) {
55894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            depth++;
5599cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski            const char16_t* ctag16 = tree.getElementName(&len);
5609cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski            if (ctag16 == NULL) {
5619cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                *outError = "failed to get XML element name (bad string pool)";
5629cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                return Vector<String8>();
5639cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski            }
5649cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski            String8 tag(ctag16);
56594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
56694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            if (depth == 1) {
56794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                if (tag == serviceTagName) {
56894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    withinApduService = true;
56994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                }
57094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            } else if (depth == 2 && withinApduService) {
57194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                if (tag == "aid-group") {
57294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    String8 category = getAttribute(tree, CATEGORY_ATTR, &error);
57394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    if (error != "") {
57494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        if (outError != NULL) *outError = error;
57594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        return Vector<String8>();
57694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    }
57794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
57894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    categories.add(category);
57994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                }
58094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            }
58194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski        }
58294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    }
58394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    aidAsset->close();
58494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    return categories;
58594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski}
58694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
5879d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinskistatic void printComponentPresence(const char* componentName) {
5889d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski    printf("provides-component:'%s'\n", componentName);
5899d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski}
5909d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski
591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Handle the "dump" command, to extract select data from an archive.
593282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiextern char CONSOLE_DATA[2925]; // see EOF
595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doDump(Bundle* bundle)
596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t result = UNKNOWN_ERROR;
598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Asset* asset = NULL;
599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getFileSpecCount() < 1) {
601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: no dump option specified\n");
602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return 1;
603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getFileSpecCount() < 2) {
606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: no dump file specified\n");
607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return 1;
608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char* option = bundle->getFileSpecEntry(0);
611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char* filename = bundle->getFileSpecEntry(1);
612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    AssetManager assets;
614f85e41f29a0e9313c2d4725f9d9648591ea49f3bNarayan Kamath    int32_t assetsCookie;
615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (!assets.addAssetPath(String8(filename), &assetsCookie)) {
616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: dump failed because assets could not be loaded\n");
617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return 1;
618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
620282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Make a dummy config for retrieving resources...  we need to supply
621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // non-default values for some configs so that we can retrieve resources
622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // in the app that don't have a default.  The most important of these is
623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // the API version because key resources like icons will have an implicit
624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // version if they are using newer config types like density.
625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ResTable_config config;
62691447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath    memset(&config, 0, sizeof(ResTable_config));
627282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    config.language[0] = 'e';
628282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    config.language[1] = 'n';
629282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    config.country[0] = 'U';
630282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    config.country[1] = 'S';
631282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    config.orientation = ResTable_config::ORIENTATION_PORT;
632282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    config.density = ResTable_config::DENSITY_MEDIUM;
633282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    config.sdkVersion = 10000; // Very high.
634282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    config.screenWidthDp = 320;
635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    config.screenHeightDp = 480;
636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    config.smallestScreenWidthDp = 320;
637282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    assets.setConfiguration(config);
638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const ResTable& res = assets.getResources(false);
640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (&res == NULL) {
641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: dump failed because no resource table was found\n");
642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
64325e9d55e964c180ec6e57ba1d977d6c2e1115f5aAdam Lesinski    } else if (res.getError() != NO_ERROR) {
64425e9d55e964c180ec6e57ba1d977d6c2e1115f5aAdam Lesinski        fprintf(stderr, "ERROR: dump failed because the resource table is invalid/corrupt.\n");
64525e9d55e964c180ec6e57ba1d977d6c2e1115f5aAdam Lesinski        goto bail;
646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
648282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (strcmp("resources", option) == 0) {
649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#ifndef HAVE_ANDROID_OS
650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        res.print(bundle->getValues());
651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif
652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else if (strcmp("strings", option) == 0) {
654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const ResStringPool* pool = res.getTableStringBlock(0);
655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printStringPool(pool);
656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else if (strcmp("xmltree", option) == 0) {
658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (bundle->getFileSpecCount() < 3) {
659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: no dump xmltree resource file specified\n");
660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (int i=2; i<bundle->getFileSpecCount(); i++) {
664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const char* resname = bundle->getFileSpecEntry(i);
665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ResXMLTree tree;
666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            asset = assets.openNonAsset(resname, Asset::ACCESS_BUFFER);
667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (asset == NULL) {
668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, "ERROR: dump failed because resource %s found\n", resname);
669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                goto bail;
670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (tree.setTo(asset->getBuffer(true),
673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           asset->getLength()) != NO_ERROR) {
674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, "ERROR: Resource %s is corrupt\n", resname);
675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                goto bail;
676282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
677282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            tree.restart();
678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printXMLBlock(&tree);
679282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            tree.uninit();
680282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            delete asset;
681282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            asset = NULL;
682282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
683282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
684282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else if (strcmp("xmlstrings", option) == 0) {
685282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (bundle->getFileSpecCount() < 3) {
686282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: no dump xmltree resource file specified\n");
687282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
690282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (int i=2; i<bundle->getFileSpecCount(); i++) {
691282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const char* resname = bundle->getFileSpecEntry(i);
692282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ResXMLTree tree;
693282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            asset = assets.openNonAsset(resname, Asset::ACCESS_BUFFER);
694282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (asset == NULL) {
695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, "ERROR: dump failed because resource %s found\n", resname);
696282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                goto bail;
697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (tree.setTo(asset->getBuffer(true),
700282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           asset->getLength()) != NO_ERROR) {
701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, "ERROR: Resource %s is corrupt\n", resname);
702282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                goto bail;
703282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
704282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printStringPool(&tree.getStrings());
705282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            delete asset;
706282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            asset = NULL;
707282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
708282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
709282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
710282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ResXMLTree tree;
711282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        asset = assets.openNonAsset("AndroidManifest.xml",
712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                            Asset::ACCESS_BUFFER);
713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (asset == NULL) {
714282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: dump failed because no AndroidManifest.xml found\n");
715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
716282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
717282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
718282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (tree.setTo(asset->getBuffer(true),
719282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       asset->getLength()) != NO_ERROR) {
720282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: AndroidManifest.xml is corrupt\n");
721282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
722282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
723282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        tree.restart();
724282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
725282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (strcmp("permissions", option) == 0) {
726282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            size_t len;
727282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ResXMLTree::event_code_t code;
728282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int depth = 0;
729282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
730282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (code == ResXMLTree::END_TAG) {
731282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    depth--;
732282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
733282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
734282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (code != ResXMLTree::START_TAG) {
735282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
736282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
737282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                depth++;
7389cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                const char16_t* ctag16 = tree.getElementName(&len);
7399cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                if (ctag16 == NULL) {
7409cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                    fprintf(stderr, "ERROR: failed to get XML element name (bad string pool)\n");
7419cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                    goto bail;
7429cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                }
7439cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                String8 tag(ctag16);
744282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                //printf("Depth %d tag %s\n", depth, tag.string());
745282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (depth == 1) {
746282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (tag != "manifest") {
747282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n");
748282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        goto bail;
749282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8 pkg = getAttribute(tree, NULL, "package", NULL);
7512675f769673f69b0661ddee346292f25cb30a296Maurice Chu                    printf("package: %s\n", ResTable::normalizeForOutput(pkg.string()).string());
752282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else if (depth == 2 && tag == "permission") {
753282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8 error;
754282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8 name = getAttribute(tree, NAME_ATTR, &error);
755282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (error != "") {
756282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        fprintf(stderr, "ERROR: %s\n", error.string());
757282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        goto bail;
758282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
7592675f769673f69b0661ddee346292f25cb30a296Maurice Chu                    printf("permission: %s\n",
7602675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            ResTable::normalizeForOutput(name.string()).string());
761282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else if (depth == 2 && tag == "uses-permission") {
762282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8 error;
763282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8 name = getAttribute(tree, NAME_ATTR, &error);
764282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (error != "") {
765282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        fprintf(stderr, "ERROR: %s\n", error.string());
766282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        goto bail;
767282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
76858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesPermission(name,
76958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                            getIntegerAttribute(tree, REQUIRED_ATTR, NULL, 1) == 0,
77058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                            getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR, NULL, -1));
771282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else if (strcmp("badging", option) == 0) {
774282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Vector<String8> locales;
775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            res.getLocales(&locales);
776282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Vector<ResTable_config> configs;
778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            res.getConfigurations(&configs);
779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            SortedVector<int> densities;
780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t NC = configs.size();
781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t i=0; i<NC; i++) {
782282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                int dens = configs[i].density;
783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (dens == 0) {
784282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    dens = 160;
785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                densities.add(dens);
787282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
788282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
789282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            size_t len;
790282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ResXMLTree::event_code_t code;
791282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int depth = 0;
792282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 error;
793282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool withinActivity = false;
794282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool isMainActivity = false;
795282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool isLauncherActivity = false;
7960a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn            bool isLeanbackLauncherActivity = false;
797282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool isSearchable = false;
798282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool withinApplication = false;
799ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright            bool withinSupportsInput = false;
800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool withinReceiver = false;
801282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool withinService = false;
8029d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool withinProvider = false;
803282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool withinIntentFilter = false;
804282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasMainActivity = false;
805282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasOtherActivities = false;
806282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasOtherReceivers = false;
807282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasOtherServices = false;
8089d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool hasIntentFilter = false;
8099d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski
810282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasWallpaperService = false;
811282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasImeService = false;
812a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool hasAccessibilityService = false;
813a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool hasPrintService = false;
814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasWidgetReceivers = false;
815a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool hasDeviceAdminReceiver = false;
81694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            bool hasPaymentService = false;
8179d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool hasDocumentsProvider = false;
8189d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool hasCameraActivity = false;
8199d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool hasCameraSecureActivity = false;
8209d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool hasLauncher = false;
8219d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool hasNotificationListenerService = false;
8229d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski
823282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool actMainActivity = false;
824282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool actWidgetReceivers = false;
825a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool actDeviceAdminEnabled = false;
826282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool actImeService = false;
827282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool actWallpaperService = false;
828a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool actAccessibilityService = false;
829a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool actPrintService = false;
83094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            bool actHostApduService = false;
83194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            bool actOffHostApduService = false;
8329d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool actDocumentsProvider = false;
8339d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool actNotificationListenerService = false;
8349d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool actCamera = false;
8359d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool actCameraSecure = false;
8369d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool catLauncher = false;
83794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            bool hasMetaHostPaymentCategory = false;
83894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            bool hasMetaOffHostPaymentCategory = false;
839a5018c900f126ee8424c82497f32983873db741bAdam Lesinski
840a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            // These permissions are required by services implementing services
841a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            // the system binds to (IME, Accessibility, PrintServices, etc.)
842a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool hasBindDeviceAdminPermission = false;
843a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool hasBindInputMethodPermission = false;
844a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool hasBindAccessibilityServicePermission = false;
845a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool hasBindPrintServicePermission = false;
84694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            bool hasBindNfcServicePermission = false;
8479d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool hasRequiredSafAttributes = false;
8489d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool hasBindNotificationListenerServicePermission = false;
849282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
850282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // These two implement the implicit permissions that are granted
851282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // to pre-1.6 applications.
852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasWriteExternalStoragePermission = false;
853282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasReadPhoneStatePermission = false;
854282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
855282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // If an app requests write storage, they will also get read storage.
856282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasReadExternalStoragePermission = false;
857282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
858282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Implement transition to read and write call log.
859282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasReadContactsPermission = false;
860282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasWriteContactsPermission = false;
861282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasReadCallLogPermission = false;
862282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasWriteCallLogPermission = false;
863282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
864282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // This next group of variables is used to implement a group of
865282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // backward-compatibility heuristics necessitated by the addition of
866282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // some new uses-feature constants in 2.1 and 2.2. In most cases, the
867282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // heuristic is "if an app requests a permission but doesn't explicitly
868282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // request the corresponding <uses-feature>, presume it's there anyway".
869282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool specCameraFeature = false; // camera-related
870282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool specCameraAutofocusFeature = false;
871282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool reqCameraAutofocusFeature = false;
872282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool reqCameraFlashFeature = false;
873282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasCameraPermission = false;
874282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool specLocationFeature = false; // location-related
875282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool specNetworkLocFeature = false;
876282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool reqNetworkLocFeature = false;
877282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool specGpsFeature = false;
878282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool reqGpsFeature = false;
879282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasMockLocPermission = false;
880282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasCoarseLocPermission = false;
881282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasGpsPermission = false;
882282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasGeneralLocPermission = false;
883282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool specBluetoothFeature = false; // Bluetooth API-related
884282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasBluetoothPermission = false;
885282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool specMicrophoneFeature = false; // microphone-related
886282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasRecordAudioPermission = false;
887282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool specWiFiFeature = false;
888282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasWiFiPermission = false;
889282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool specTelephonyFeature = false; // telephony-related
890282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool reqTelephonySubFeature = false;
891282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasTelephonyPermission = false;
892282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool specTouchscreenFeature = false; // touchscreen-related
893282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool specMultitouchFeature = false;
894282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool reqDistinctMultitouchFeature = false;
895282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool specScreenPortraitFeature = false;
896282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool specScreenLandscapeFeature = false;
897282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool reqScreenPortraitFeature = false;
898282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool reqScreenLandscapeFeature = false;
899282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // 2.2 also added some other features that apps can request, but that
900282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // have no corresponding permission, so we cannot implement any
901282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // back-compatibility heuristic for them. The below are thus unnecessary
902282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // (but are retained here for documentary purposes.)
903282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //bool specCompassFeature = false;
904282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //bool specAccelerometerFeature = false;
905282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //bool specProximityFeature = false;
906282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //bool specAmbientLightFeature = false;
907282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //bool specLiveWallpaperFeature = false;
908282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
909282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int targetSdk = 0;
910282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int smallScreen = 1;
911282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int normalScreen = 1;
912282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int largeScreen = 1;
913282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int xlargeScreen = 1;
914282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int anyDensity = 1;
915282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int requiresSmallestWidthDp = 0;
916282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int compatibleWidthLimitDp = 0;
917282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int largestWidthLimitDp = 0;
918282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 pkg;
919282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 activityName;
920282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 activityLabel;
921282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 activityIcon;
9220a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn            String8 activityBanner;
923282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 receiverName;
924282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 serviceName;
925ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright            Vector<String8> supportedInput;
926282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
927282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (code == ResXMLTree::END_TAG) {
928282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    depth--;
929282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (depth < 2) {
930ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        if (withinSupportsInput && !supportedInput.isEmpty()) {
931ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            printf("supports-input: '");
932ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            const size_t N = supportedInput.size();
933ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            for (size_t i=0; i<N; i++) {
9342675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                printf("%s", ResTable::normalizeForOutput(
9352675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                        supportedInput[i].string()).string());
936ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                if (i != N - 1) {
937ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                    printf("' '");
938ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                } else {
939ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                    printf("'\n");
940ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                }
941ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
942ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            supportedInput.clear();
943ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        }
944282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        withinApplication = false;
945ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        withinSupportsInput = false;
946282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (depth < 3) {
9470a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                        if (withinActivity && isMainActivity) {
9482675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            String8 aName(getComponentName(pkg, activityName));
9490a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                            if (isLauncherActivity) {
9500a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                printf("launchable-activity:");
9519eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                if (aName.length() > 0) {
9529eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                    printf(" name='%s' ",
9539eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                            ResTable::normalizeForOutput(aName.string()).string());
9540a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                }
9550a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                printf(" label='%s' icon='%s'\n",
9569eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                        ResTable::normalizeForOutput(activityLabel.string()).string(),
9579eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                        ResTable::normalizeForOutput(activityIcon.string()).string());
9580a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                            }
9590a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                            if (isLeanbackLauncherActivity) {
9600a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                printf("leanback-launchable-activity:");
9619eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                if (aName.length() > 0) {
9629eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                    printf(" name='%s' ",
9639eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                            ResTable::normalizeForOutput(aName.string()).string());
9640a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                }
9650a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                printf(" label='%s' icon='%s' banner='%s'\n",
9669eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                        ResTable::normalizeForOutput(activityLabel.string()).string(),
9679eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                        ResTable::normalizeForOutput(activityIcon.string()).string(),
9689eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                        ResTable::normalizeForOutput(activityBanner.string()).string());
969282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
970282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
971282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (!hasIntentFilter) {
972282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            hasOtherActivities |= withinActivity;
973282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            hasOtherReceivers |= withinReceiver;
974282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            hasOtherServices |= withinService;
97594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        } else {
97694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            if (withinService) {
97794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                hasPaymentService |= (actHostApduService && hasMetaHostPaymentCategory &&
97894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                        hasBindNfcServicePermission);
97994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                hasPaymentService |= (actOffHostApduService && hasMetaOffHostPaymentCategory &&
98094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                        hasBindNfcServicePermission);
98194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            }
982282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
983282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        withinActivity = false;
984282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        withinService = false;
985282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        withinReceiver = false;
9869d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                        withinProvider = false;
987282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasIntentFilter = false;
9880a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                        isMainActivity = isLauncherActivity = isLeanbackLauncherActivity = false;
989282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (depth < 4) {
990282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (withinIntentFilter) {
991282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (withinActivity) {
992282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasMainActivity |= actMainActivity;
9939d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                hasLauncher |= catLauncher;
9949d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                hasCameraActivity |= actCamera;
9959d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                hasCameraSecureActivity |= actCameraSecure;
9969d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                hasOtherActivities |= !actMainActivity && !actCamera && !actCameraSecure;
997282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (withinReceiver) {
998282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasWidgetReceivers |= actWidgetReceivers;
999a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                hasDeviceAdminReceiver |= (actDeviceAdminEnabled &&
1000a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                        hasBindDeviceAdminPermission);
1001a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                hasOtherReceivers |= (!actWidgetReceivers && !actDeviceAdminEnabled);
1002282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (withinService) {
1003282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasImeService |= actImeService;
1004282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasWallpaperService |= actWallpaperService;
1005a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                hasAccessibilityService |= (actAccessibilityService &&
1006a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                        hasBindAccessibilityServicePermission);
1007a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                hasPrintService |= (actPrintService && hasBindPrintServicePermission);
10089d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                hasNotificationListenerService |= actNotificationListenerService &&
10099d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                        hasBindNotificationListenerServicePermission;
1010a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                hasOtherServices |= (!actImeService && !actWallpaperService &&
101194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                        !actAccessibilityService && !actPrintService &&
10129d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                        !actHostApduService && !actOffHostApduService &&
10139d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                        !actNotificationListenerService);
10149d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            } else if (withinProvider) {
10159d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                hasDocumentsProvider |= actDocumentsProvider && hasRequiredSafAttributes;
1016282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1017282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1018282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        withinIntentFilter = false;
1019282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1020282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
1021282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1022282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (code != ResXMLTree::START_TAG) {
1023282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
1024282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1025282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                depth++;
10269cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski
10279cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                const char16_t* ctag16 = tree.getElementName(&len);
10289cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                if (ctag16 == NULL) {
10299cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                    fprintf(stderr, "ERROR: failed to get XML element name (bad string pool)\n");
10309cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                    goto bail;
10319cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                }
10329cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                String8 tag(ctag16);
1033282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                //printf("Depth %d,  %s\n", depth, tag.string());
1034282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (depth == 1) {
1035282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (tag != "manifest") {
1036282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n");
1037282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        goto bail;
1038282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1039282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    pkg = getAttribute(tree, NULL, "package", NULL);
10402675f769673f69b0661ddee346292f25cb30a296Maurice Chu                    printf("package: name='%s' ",
10412675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            ResTable::normalizeForOutput(pkg.string()).string());
1042282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    int32_t versionCode = getIntegerAttribute(tree, VERSION_CODE_ATTR, &error);
1043282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (error != "") {
1044282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        fprintf(stderr, "ERROR getting 'android:versionCode' attribute: %s\n", error.string());
1045282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        goto bail;
1046282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1047282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (versionCode > 0) {
1048282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        printf("versionCode='%d' ", versionCode);
1049282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else {
1050282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        printf("versionCode='' ");
1051282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1052282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8 versionName = getResolvedAttribute(&res, tree, VERSION_NAME_ATTR, &error);
1053282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (error != "") {
1054282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        fprintf(stderr, "ERROR getting 'android:versionName' attribute: %s\n", error.string());
1055282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        goto bail;
1056282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
10572675f769673f69b0661ddee346292f25cb30a296Maurice Chu                    printf("versionName='%s'\n",
10582675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            ResTable::normalizeForOutput(versionName.string()).string());
1059282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else if (depth == 2) {
1060282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    withinApplication = false;
1061282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (tag == "application") {
1062282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        withinApplication = true;
1063282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1064282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8 label;
1065282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const size_t NL = locales.size();
1066282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        for (size_t i=0; i<NL; i++) {
1067282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            const char* localeStr =  locales[i].string();
1068282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            assets.setLocale(localeStr != NULL ? localeStr : "");
1069282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            String8 llabel = getResolvedAttribute(&res, tree, LABEL_ATTR, &error);
1070282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (llabel != "") {
1071282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                if (localeStr == NULL || strlen(localeStr) == 0) {
1072282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    label = llabel;
10732675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                    printf("application-label:'%s'\n",
10742675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                            ResTable::normalizeForOutput(llabel.string()).string());
1075282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                } else {
1076282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    if (label == "") {
1077282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        label = llabel;
1078282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    }
1079282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    printf("application-label-%s:'%s'\n", localeStr,
10802675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                           ResTable::normalizeForOutput(llabel.string()).string());
1081282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                }
1082282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1083282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1084282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1085282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ResTable_config tmpConfig = config;
1086282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const size_t ND = densities.size();
1087282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        for (size_t i=0; i<ND; i++) {
1088282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            tmpConfig.density = densities[i];
1089282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            assets.setConfiguration(tmpConfig);
1090282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            String8 icon = getResolvedAttribute(&res, tree, ICON_ATTR, &error);
1091282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (icon != "") {
10922675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                printf("application-icon-%d:'%s'\n", densities[i],
10932675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                        ResTable::normalizeForOutput(icon.string()).string());
1094282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1095282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1096282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        assets.setConfiguration(config);
1097282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1098282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8 icon = getResolvedAttribute(&res, tree, ICON_ATTR, &error);
1099282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (error != "") {
1100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n", error.string());
1101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            goto bail;
1102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        int32_t testOnly = getIntegerAttribute(tree, TEST_ONLY_ATTR, &error, 0);
1104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (error != "") {
1105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            fprintf(stderr, "ERROR getting 'android:testOnly' attribute: %s\n", error.string());
1106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            goto bail;
1107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
11082675f769673f69b0661ddee346292f25cb30a296Maurice Chu                        printf("application: label='%s' ",
11092675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                ResTable::normalizeForOutput(label.string()).string());
11102675f769673f69b0661ddee346292f25cb30a296Maurice Chu                        printf("icon='%s'\n", ResTable::normalizeForOutput(icon.string()).string());
1111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (testOnly != 0) {
1112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf("testOnly='%d'\n", testOnly);
1113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        int32_t debuggable = getResolvedIntegerAttribute(&res, tree, DEBUGGABLE_ATTR, &error, 0);
1116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (error != "") {
1117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            fprintf(stderr, "ERROR getting 'android:debuggable' attribute: %s\n", error.string());
1118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            goto bail;
1119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (debuggable != 0) {
1121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf("application-debuggable\n");
1122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "uses-sdk") {
1124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        int32_t code = getIntegerAttribute(tree, MIN_SDK_VERSION_ATTR, &error);
1125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (error != "") {
1126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            error = "";
1127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            String8 name = getResolvedAttribute(&res, tree, MIN_SDK_VERSION_ATTR, &error);
1128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (error != "") {
1129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                fprintf(stderr, "ERROR getting 'android:minSdkVersion' attribute: %s\n",
1130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        error.string());
1131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                goto bail;
1132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (name == "Donut") targetSdk = 4;
11342675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            printf("sdkVersion:'%s'\n",
11352675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                    ResTable::normalizeForOutput(name.string()).string());
1136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else if (code != -1) {
1137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            targetSdk = code;
1138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf("sdkVersion:'%d'\n", code);
1139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        code = getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR, NULL, -1);
1141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (code != -1) {
1142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf("maxSdkVersion:'%d'\n", code);
1143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        code = getIntegerAttribute(tree, TARGET_SDK_VERSION_ATTR, &error);
1145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (error != "") {
1146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            error = "";
1147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            String8 name = getResolvedAttribute(&res, tree, TARGET_SDK_VERSION_ATTR, &error);
1148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (error != "") {
1149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                fprintf(stderr, "ERROR getting 'android:targetSdkVersion' attribute: %s\n",
1150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        error.string());
1151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                goto bail;
1152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (name == "Donut" && targetSdk < 4) targetSdk = 4;
11542675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            printf("targetSdkVersion:'%s'\n",
11552675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                    ResTable::normalizeForOutput(name.string()).string());
1156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else if (code != -1) {
1157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (targetSdk < code) {
1158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                targetSdk = code;
1159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf("targetSdkVersion:'%d'\n", code);
1161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "uses-configuration") {
1163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        int32_t reqTouchScreen = getIntegerAttribute(tree,
1164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                REQ_TOUCH_SCREEN_ATTR, NULL, 0);
1165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        int32_t reqKeyboardType = getIntegerAttribute(tree,
1166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                REQ_KEYBOARD_TYPE_ATTR, NULL, 0);
1167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        int32_t reqHardKeyboard = getIntegerAttribute(tree,
1168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                REQ_HARD_KEYBOARD_ATTR, NULL, 0);
1169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        int32_t reqNavigation = getIntegerAttribute(tree,
1170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                REQ_NAVIGATION_ATTR, NULL, 0);
1171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        int32_t reqFiveWayNav = getIntegerAttribute(tree,
1172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                REQ_FIVE_WAY_NAV_ATTR, NULL, 0);
1173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        printf("uses-configuration:");
1174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (reqTouchScreen != 0) {
1175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf(" reqTouchScreen='%d'", reqTouchScreen);
1176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (reqKeyboardType != 0) {
1178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf(" reqKeyboardType='%d'", reqKeyboardType);
1179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (reqHardKeyboard != 0) {
1181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf(" reqHardKeyboard='%d'", reqHardKeyboard);
1182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (reqNavigation != 0) {
1184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf(" reqNavigation='%d'", reqNavigation);
1185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (reqFiveWayNav != 0) {
1187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf(" reqFiveWayNav='%d'", reqFiveWayNav);
1188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        printf("\n");
1190ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                    } else if (tag == "supports-input") {
1191ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        withinSupportsInput = true;
1192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "supports-screens") {
1193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        smallScreen = getIntegerAttribute(tree,
1194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                SMALL_SCREEN_ATTR, NULL, 1);
1195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        normalScreen = getIntegerAttribute(tree,
1196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                NORMAL_SCREEN_ATTR, NULL, 1);
1197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        largeScreen = getIntegerAttribute(tree,
1198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                LARGE_SCREEN_ATTR, NULL, 1);
1199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        xlargeScreen = getIntegerAttribute(tree,
1200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                XLARGE_SCREEN_ATTR, NULL, 1);
1201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        anyDensity = getIntegerAttribute(tree,
1202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                ANY_DENSITY_ATTR, NULL, 1);
1203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        requiresSmallestWidthDp = getIntegerAttribute(tree,
1204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                REQUIRES_SMALLEST_WIDTH_DP_ATTR, NULL, 0);
1205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        compatibleWidthLimitDp = getIntegerAttribute(tree,
1206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                COMPATIBLE_WIDTH_LIMIT_DP_ATTR, NULL, 0);
1207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        largestWidthLimitDp = getIntegerAttribute(tree,
1208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                LARGEST_WIDTH_LIMIT_DP_ATTR, NULL, 0);
1209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "uses-feature") {
1210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8 name = getAttribute(tree, NAME_ATTR, &error);
1211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (name != "" && error == "") {
1213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            int req = getIntegerAttribute(tree,
1214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    REQUIRED_ATTR, NULL, 1);
1215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (name == "android.hardware.camera") {
1217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                specCameraFeature = true;
1218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.hardware.camera.autofocus") {
1219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                // these have no corresponding permission to check for,
1220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                // but should imply the foundational camera permission
1221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                reqCameraAutofocusFeature = reqCameraAutofocusFeature || req;
1222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                specCameraAutofocusFeature = true;
1223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (req && (name == "android.hardware.camera.flash")) {
1224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                // these have no corresponding permission to check for,
1225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                // but should imply the foundational camera permission
1226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                reqCameraFlashFeature = true;
1227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.hardware.location") {
1228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                specLocationFeature = true;
1229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.hardware.location.network") {
1230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                specNetworkLocFeature = true;
1231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                reqNetworkLocFeature = reqNetworkLocFeature || req;
1232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.hardware.location.gps") {
1233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                specGpsFeature = true;
1234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                reqGpsFeature = reqGpsFeature || req;
1235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.hardware.bluetooth") {
1236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                specBluetoothFeature = true;
1237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.hardware.touchscreen") {
1238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                specTouchscreenFeature = true;
1239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.hardware.touchscreen.multitouch") {
1240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                specMultitouchFeature = true;
1241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.hardware.touchscreen.multitouch.distinct") {
1242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                reqDistinctMultitouchFeature = reqDistinctMultitouchFeature || req;
1243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.hardware.microphone") {
1244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                specMicrophoneFeature = true;
1245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.hardware.wifi") {
1246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                specWiFiFeature = true;
1247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.hardware.telephony") {
1248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                specTelephonyFeature = true;
1249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (req && (name == "android.hardware.telephony.gsm" ||
1250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                               name == "android.hardware.telephony.cdma")) {
1251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                // these have no corresponding permission to check for,
1252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                // but should imply the foundational telephony permission
1253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                reqTelephonySubFeature = true;
1254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.hardware.screen.portrait") {
1255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                specScreenPortraitFeature = true;
1256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.hardware.screen.landscape") {
1257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                specScreenLandscapeFeature = true;
1258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf("uses-feature%s:'%s'\n",
12602675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                    req ? "" : "-not-required",
12612675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                            ResTable::normalizeForOutput(name.string()).string());
1262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else {
1263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            int vers = getIntegerAttribute(tree,
1264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    GL_ES_VERSION_ATTR, &error);
1265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (error == "") {
1266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                printf("uses-gl-es:'0x%x'\n", vers);
1267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "uses-permission") {
1270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8 name = getAttribute(tree, NAME_ATTR, &error);
1271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (name != "" && error == "") {
1272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (name == "android.permission.CAMERA") {
1273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasCameraPermission = true;
1274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.ACCESS_FINE_LOCATION") {
1275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasGpsPermission = true;
1276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.ACCESS_MOCK_LOCATION") {
1277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasMockLocPermission = true;
1278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.ACCESS_COARSE_LOCATION") {
1279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasCoarseLocPermission = true;
1280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" ||
1281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.INSTALL_LOCATION_PROVIDER") {
1282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasGeneralLocPermission = true;
1283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.BLUETOOTH" ||
1284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.BLUETOOTH_ADMIN") {
1285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasBluetoothPermission = true;
1286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.RECORD_AUDIO") {
1287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasRecordAudioPermission = true;
1288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.ACCESS_WIFI_STATE" ||
1289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.CHANGE_WIFI_STATE" ||
1290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.CHANGE_WIFI_MULTICAST_STATE") {
1291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasWiFiPermission = true;
1292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.CALL_PHONE" ||
1293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.CALL_PRIVILEGED" ||
1294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.MODIFY_PHONE_STATE" ||
1295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.PROCESS_OUTGOING_CALLS" ||
1296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.READ_SMS" ||
1297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.RECEIVE_SMS" ||
1298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.RECEIVE_MMS" ||
1299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.RECEIVE_WAP_PUSH" ||
1300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.SEND_SMS" ||
1301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.WRITE_APN_SETTINGS" ||
1302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.WRITE_SMS") {
1303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasTelephonyPermission = true;
1304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.WRITE_EXTERNAL_STORAGE") {
1305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasWriteExternalStoragePermission = true;
1306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.READ_EXTERNAL_STORAGE") {
1307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasReadExternalStoragePermission = true;
1308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.READ_PHONE_STATE") {
1309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasReadPhoneStatePermission = true;
1310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.READ_CONTACTS") {
1311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasReadContactsPermission = true;
1312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.WRITE_CONTACTS") {
1313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasWriteContactsPermission = true;
1314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.READ_CALL_LOG") {
1315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasReadCallLogPermission = true;
1316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.WRITE_CALL_LOG") {
1317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasWriteCallLogPermission = true;
1318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
131958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski
132058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                            printUsesPermission(name,
132158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                                    getIntegerAttribute(tree, REQUIRED_ATTR, NULL, 1) == 0,
132258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                                    getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR, NULL, -1));
132358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                       } else {
1324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    error.string());
1326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            goto bail;
1327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "uses-package") {
1329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8 name = getAttribute(tree, NAME_ATTR, &error);
1330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (name != "" && error == "") {
13312675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            printf("uses-package:'%s'\n",
13322675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                    ResTable::normalizeForOutput(name.string()).string());
1333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else {
1334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    error.string());
1336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                goto bail;
1337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "original-package") {
1339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8 name = getAttribute(tree, NAME_ATTR, &error);
1340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (name != "" && error == "") {
13412675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            printf("original-package:'%s'\n",
13422675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                    ResTable::normalizeForOutput(name.string()).string());
1343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else {
1344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    error.string());
1346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                goto bail;
1347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "supports-gl-texture") {
1349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8 name = getAttribute(tree, NAME_ATTR, &error);
1350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (name != "" && error == "") {
13512675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            printf("supports-gl-texture:'%s'\n",
13522675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                    ResTable::normalizeForOutput(name.string()).string());
1353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else {
1354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    error.string());
1356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                goto bail;
1357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "compatible-screens") {
13599cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                        printCompatibleScreens(tree, &error);
13609cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                        if (error != "") {
13619cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                            fprintf(stderr, "ERROR getting compatible screens: %s\n",
13629cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                                    error.string());
13639cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                            goto bail;
13649cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                        }
1365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        depth--;
1366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "package-verifier") {
1367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8 name = getAttribute(tree, NAME_ATTR, &error);
1368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (name != "" && error == "") {
1369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            String8 publicKey = getAttribute(tree, PUBLIC_KEY_ATTR, &error);
1370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (publicKey != "" && error == "") {
1371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                printf("package-verifier: name='%s' publicKey='%s'\n",
13722675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                        ResTable::normalizeForOutput(name.string()).string(),
13732675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                        ResTable::normalizeForOutput(publicKey.string()).string());
1374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1377ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                } else if (depth == 3) {
1378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    withinActivity = false;
1379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    withinReceiver = false;
1380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    withinService = false;
13819d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                    withinProvider = false;
1382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasIntentFilter = false;
138394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    hasMetaHostPaymentCategory = false;
138494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    hasMetaOffHostPaymentCategory = false;
138594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    hasBindDeviceAdminPermission = false;
138694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    hasBindInputMethodPermission = false;
138794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    hasBindAccessibilityServicePermission = false;
138894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    hasBindPrintServicePermission = false;
138994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    hasBindNfcServicePermission = false;
13909d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                    hasRequiredSafAttributes = false;
13919d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                    hasBindNotificationListenerServicePermission = false;
1392ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                    if (withinApplication) {
1393ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        if(tag == "activity") {
1394ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            withinActivity = true;
1395ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            activityName = getAttribute(tree, NAME_ATTR, &error);
1396ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (error != "") {
1397ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1398ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        error.string());
1399ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                goto bail;
1400ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
1401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1402ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            activityLabel = getResolvedAttribute(&res, tree, LABEL_ATTR, &error);
1403ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (error != "") {
1404ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                fprintf(stderr, "ERROR getting 'android:label' attribute: %s\n",
1405ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        error.string());
1406ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                goto bail;
1407ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
1408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1409ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            activityIcon = getResolvedAttribute(&res, tree, ICON_ATTR, &error);
1410ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (error != "") {
1411ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n",
1412ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        error.string());
1413ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                goto bail;
1414ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
1415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
14160a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                            activityBanner = getResolvedAttribute(&res, tree, BANNER_ATTR, &error);
14170a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                            if (error != "") {
14180a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                fprintf(stderr, "ERROR getting 'android:banner' attribute: %s\n",
14190a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                        error.string());
14200a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                goto bail;
14210a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                            }
14220a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn
1423ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            int32_t orien = getResolvedIntegerAttribute(&res, tree,
1424ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                    SCREEN_ORIENTATION_ATTR, &error);
1425ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (error == "") {
1426ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                if (orien == 0 || orien == 6 || orien == 8) {
1427ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                    // Requests landscape, sensorLandscape, or reverseLandscape.
1428ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                    reqScreenLandscapeFeature = true;
1429ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                } else if (orien == 1 || orien == 7 || orien == 9) {
1430ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                    // Requests portrait, sensorPortrait, or reversePortrait.
1431ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                    reqScreenPortraitFeature = true;
1432ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                }
1433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1434ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        } else if (tag == "uses-library") {
1435ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            String8 libraryName = getAttribute(tree, NAME_ATTR, &error);
1436ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (error != "") {
1437ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                fprintf(stderr,
1438ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        "ERROR getting 'android:name' attribute for uses-library"
1439ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        " %s\n", error.string());
1440ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                goto bail;
1441ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
1442ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            int req = getIntegerAttribute(tree,
1443ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                    REQUIRED_ATTR, NULL, 1);
1444ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            printf("uses-library%s:'%s'\n",
14452675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                    req ? "" : "-not-required", ResTable::normalizeForOutput(
14462675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                            libraryName.string()).string());
1447ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        } else if (tag == "receiver") {
1448ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            withinReceiver = true;
1449ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            receiverName = getAttribute(tree, NAME_ATTR, &error);
1450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1451ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (error != "") {
1452ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                fprintf(stderr,
1453ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        "ERROR getting 'android:name' attribute for receiver:"
1454ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        " %s\n", error.string());
1455ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                goto bail;
1456ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
1457a5018c900f126ee8424c82497f32983873db741bAdam Lesinski
1458a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            String8 permission = getAttribute(tree, PERMISSION_ATTR, &error);
1459a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            if (error == "") {
1460a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                if (permission == "android.permission.BIND_DEVICE_ADMIN") {
1461a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                    hasBindDeviceAdminPermission = true;
1462a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                }
1463a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            } else {
1464a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                fprintf(stderr, "ERROR getting 'android:permission' attribute for"
1465a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                        " receiver '%s': %s\n", receiverName.string(), error.string());
1466a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            }
1467ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        } else if (tag == "service") {
1468ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            withinService = true;
1469ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            serviceName = getAttribute(tree, NAME_ATTR, &error);
1470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1471ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (error != "") {
1472ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                fprintf(stderr, "ERROR getting 'android:name' attribute for "
1473ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        "service:%s\n", error.string());
1474ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                goto bail;
1475ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
1476a5018c900f126ee8424c82497f32983873db741bAdam Lesinski
1477a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            String8 permission = getAttribute(tree, PERMISSION_ATTR, &error);
1478a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            if (error == "") {
1479a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                if (permission == "android.permission.BIND_INPUT_METHOD") {
1480a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                    hasBindInputMethodPermission = true;
1481a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                } else if (permission == "android.permission.BIND_ACCESSIBILITY_SERVICE") {
1482a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                    hasBindAccessibilityServicePermission = true;
1483a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                } else if (permission == "android.permission.BIND_PRINT_SERVICE") {
1484a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                    hasBindPrintServicePermission = true;
148594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                } else if (permission == "android.permission.BIND_NFC_SERVICE") {
148694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                    hasBindNfcServicePermission = true;
14879d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                } else if (permission == "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE") {
14889d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                    hasBindNotificationListenerServicePermission = true;
1489a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                }
1490a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            } else {
1491a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                fprintf(stderr, "ERROR getting 'android:permission' attribute for"
1492a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                        " service '%s': %s\n", serviceName.string(), error.string());
1493a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            }
14949d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                        } else if (tag == "provider") {
14959d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            withinProvider = true;
14969d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski
14979d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            bool exported = getResolvedIntegerAttribute(&res, tree, EXPORTED_ATTR, &error);
14989d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            if (error != "") {
14999d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                fprintf(stderr, "ERROR getting 'android:exported' attribute for provider:"
15009d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                        " %s\n", error.string());
15019d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                goto bail;
15029d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            }
15039d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski
15049d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            bool grantUriPermissions = getResolvedIntegerAttribute(&res, tree,
15059d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                    GRANT_URI_PERMISSIONS_ATTR, &error);
15069d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            if (error != "") {
15079d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                fprintf(stderr, "ERROR getting 'android:grantUriPermissions' attribute for provider:"
15089d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                        " %s\n", error.string());
15099d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                goto bail;
15109d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            }
15119d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski
15129d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            String8 permission = getResolvedAttribute(&res, tree, PERMISSION_ATTR, &error);
15139d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            if (error != "") {
15149d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                fprintf(stderr, "ERROR getting 'android:permission' attribute for provider:"
15159d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                        " %s\n", error.string());
15169d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                goto bail;
15179d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            }
15189d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski
15199d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            hasRequiredSafAttributes |= exported && grantUriPermissions &&
15209d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                permission == "android.permission.MANAGE_DOCUMENTS";
15219d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski
1522ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        } else if (bundle->getIncludeMetaData() && tag == "meta-data") {
1523b71adb6571aa740f4fa794602133f708e1b96545Adam Lesinski                            String8 metaDataName = getResolvedAttribute(&res, tree, NAME_ATTR, &error);
1524ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (error != "") {
1525ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                fprintf(stderr, "ERROR getting 'android:name' attribute for "
1526ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        "meta-data:%s\n", error.string());
1527ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                goto bail;
1528ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
15292675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            printf("meta-data: name='%s' ",
15302675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                    ResTable::normalizeForOutput(metaDataName.string()).string());
153176327314d2238e105f8b94909f9c0cf85caca318Maurice Chu                            printResolvedResourceAttribute(&res, tree, VALUE_ATTR, String8("value"),
153276327314d2238e105f8b94909f9c0cf85caca318Maurice Chu                                    &error);
1533282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (error != "") {
153476327314d2238e105f8b94909f9c0cf85caca318Maurice Chu                                // Try looking for a RESOURCE_ATTR
153576327314d2238e105f8b94909f9c0cf85caca318Maurice Chu                                error = "";
153676327314d2238e105f8b94909f9c0cf85caca318Maurice Chu                                printResolvedResourceAttribute(&res, tree, RESOURCE_ATTR,
153776327314d2238e105f8b94909f9c0cf85caca318Maurice Chu                                        String8("resource"), &error);
1538ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                if (error != "") {
153976327314d2238e105f8b94909f9c0cf85caca318Maurice Chu                                    fprintf(stderr, "ERROR getting 'android:value' or "
154076327314d2238e105f8b94909f9c0cf85caca318Maurice Chu                                            "'android:resource' attribute for "
154176327314d2238e105f8b94909f9c0cf85caca318Maurice Chu                                            "meta-data:%s\n", error.string());
1542ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                    goto bail;
1543ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                }
1544ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
154576327314d2238e105f8b94909f9c0cf85caca318Maurice Chu                            printf("\n");
1546ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        } else if (withinSupportsInput && tag == "input-type") {
1547ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            String8 name = getAttribute(tree, NAME_ATTR, &error);
1548ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (name != "" && error == "") {
1549ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                supportedInput.add(name);
1550ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            } else {
1551ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1552ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        error.string());
1553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                goto bail;
1554282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1555282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1556a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                    }
155794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                } else if (depth == 4) {
155894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    if (tag == "intent-filter") {
155994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        hasIntentFilter = true;
156094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        withinIntentFilter = true;
156194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actMainActivity = false;
156294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actWidgetReceivers = false;
156394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actImeService = false;
156494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actWallpaperService = false;
156594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actAccessibilityService = false;
156694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actPrintService = false;
156794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actDeviceAdminEnabled = false;
156894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actHostApduService = false;
156994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actOffHostApduService = false;
15709d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                        actDocumentsProvider = false;
15719d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                        actNotificationListenerService = false;
15729d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                        actCamera = false;
15739d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                        actCameraSecure = false;
15749d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                        catLauncher = false;
157594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    } else if (withinService && tag == "meta-data") {
157694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        String8 name = getAttribute(tree, NAME_ATTR, &error);
157794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        if (error != "") {
157894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            fprintf(stderr, "ERROR getting 'android:name' attribute for"
157994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                    " meta-data tag in service '%s': %s\n", serviceName.string(), error.string());
158094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            goto bail;
158194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        }
158294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
158394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        if (name == "android.nfc.cardemulation.host_apdu_service" ||
158494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                name == "android.nfc.cardemulation.off_host_apdu_service") {
158594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            bool offHost = true;
158694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            if (name == "android.nfc.cardemulation.host_apdu_service") {
158794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                offHost = false;
158894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            }
158994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
159094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            String8 xmlPath = getResolvedAttribute(&res, tree, RESOURCE_ATTR, &error);
159194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            if (error != "") {
159294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                fprintf(stderr, "ERROR getting 'android:resource' attribute for"
159394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                        " meta-data tag in service '%s': %s\n", serviceName.string(), error.string());
159494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                goto bail;
159594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            }
159694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
159794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            Vector<String8> categories = getNfcAidCategories(assets, xmlPath,
159894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                    offHost, &error);
159994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            if (error != "") {
160094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                fprintf(stderr, "ERROR getting AID category for service '%s'\n",
160194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                        serviceName.string());
160294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                goto bail;
160394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            }
160494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
160594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            const size_t catLen = categories.size();
160694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            for (size_t i = 0; i < catLen; i++) {
160794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                bool paymentCategory = (categories[i] == "payment");
160894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                if (offHost) {
160994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                    hasMetaOffHostPaymentCategory |= paymentCategory;
161094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                } else {
161194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                    hasMetaHostPaymentCategory |= paymentCategory;
161294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                }
161394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            }
161494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        }
161594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    }
1616a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                } else if ((depth == 5) && withinIntentFilter) {
1617a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                    String8 action;
1618a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                    if (tag == "action") {
1619a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        action = getAttribute(tree, NAME_ATTR, &error);
1620a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        if (error != "") {
1621a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1622a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                    error.string());
1623a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            goto bail;
1624a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        }
1625a5018c900f126ee8424c82497f32983873db741bAdam Lesinski
1626a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        if (withinActivity) {
1627a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            if (action == "android.intent.action.MAIN") {
1628a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                isMainActivity = true;
1629a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                actMainActivity = true;
16309d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            } else if (action == "android.media.action.STILL_IMAGE_CAMERA" ||
16319d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                    action == "android.media.action.VIDEO_CAMERA") {
16329d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                actCamera = true;
16339d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            } else if (action == "android.media.action.STILL_IMAGE_CAMERA_SECURE") {
16349d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                actCameraSecure = true;
1635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1636a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        } else if (withinReceiver) {
1637a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            if (action == "android.appwidget.action.APPWIDGET_UPDATE") {
1638a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                actWidgetReceivers = true;
1639a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            } else if (action == "android.app.action.DEVICE_ADMIN_ENABLED") {
1640a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                actDeviceAdminEnabled = true;
1641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1642a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        } else if (withinService) {
1643a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            if (action == "android.view.InputMethod") {
1644a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                actImeService = true;
1645a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            } else if (action == "android.service.wallpaper.WallpaperService") {
1646a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                actWallpaperService = true;
1647a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            } else if (action == "android.accessibilityservice.AccessibilityService") {
1648a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                actAccessibilityService = true;
1649a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            } else if (action == "android.printservice.PrintService") {
1650a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                actPrintService = true;
165194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            } else if (action == "android.nfc.cardemulation.action.HOST_APDU_SERVICE") {
165294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                actHostApduService = true;
165394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            } else if (action == "android.nfc.cardemulation.action.OFF_HOST_APDU_SERVICE") {
165494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                actOffHostApduService = true;
16559d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            } else if (action == "android.service.notification.NotificationListenerService") {
16569d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                actNotificationListenerService = true;
16579d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            }
16589d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                        } else if (withinProvider) {
16599d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            if (action == "android.content.action.DOCUMENTS_PROVIDER") {
16609d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                actDocumentsProvider = true;
1661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1663a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        if (action == "android.intent.action.SEARCH") {
1664a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            isSearchable = true;
1665a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        }
1666a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                    }
1667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1668a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                    if (tag == "category") {
1669a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        String8 category = getAttribute(tree, NAME_ATTR, &error);
1670a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        if (error != "") {
1671a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            fprintf(stderr, "ERROR getting 'name' attribute: %s\n",
1672a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                    error.string());
1673a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            goto bail;
1674a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        }
1675a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        if (withinActivity) {
1676a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            if (category == "android.intent.category.LAUNCHER") {
1677a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                isLauncherActivity = true;
16780a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                            } else if (category == "android.intent.category.LEANBACK_LAUNCHER") {
16790a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                isLeanbackLauncherActivity = true;
16809d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            } else if (category == "android.intent.category.HOME") {
16819d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                catLauncher = true;
1682282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1683282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1684282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1685282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1686282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1687282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Pre-1.6 implicitly granted permission compatibility logic
1689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (targetSdk < 4) {
1690282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!hasWriteExternalStoragePermission) {
169158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesPermission(String8("android.permission.WRITE_EXTERNAL_STORAGE"));
169258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesImpliedPermission(String8("android.permission.WRITE_EXTERNAL_STORAGE"),
169358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                            String8("targetSdkVersion < 4"));
1694282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasWriteExternalStoragePermission = true;
1695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1696282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!hasReadPhoneStatePermission) {
169758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesPermission(String8("android.permission.READ_PHONE_STATE"));
169858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesImpliedPermission(String8("android.permission.READ_PHONE_STATE"),
169958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                            String8("targetSdkVersion < 4"));
1700282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1702282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1703282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // If the application has requested WRITE_EXTERNAL_STORAGE, we will
1704282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // force them to always take READ_EXTERNAL_STORAGE as well.  We always
1705282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // do this (regardless of target API version) because we can't have
1706282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // an app with write permission but not read permission.
1707282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!hasReadExternalStoragePermission && hasWriteExternalStoragePermission) {
170858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                printUsesPermission(String8("android.permission.READ_EXTERNAL_STORAGE"));
170958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                printUsesImpliedPermission(String8("android.permission.READ_EXTERNAL_STORAGE"),
171058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                        String8("requested WRITE_EXTERNAL_STORAGE"));
1711282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Pre-JellyBean call log permission compatibility.
1714282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (targetSdk < 16) {
1715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!hasReadCallLogPermission && hasReadContactsPermission) {
171658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesPermission(String8("android.permission.READ_CALL_LOG"));
171758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesImpliedPermission(String8("android.permission.READ_CALL_LOG"),
171858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                            String8("targetSdkVersion < 16 and requested READ_CONTACTS"));
1719282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1720282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!hasWriteCallLogPermission && hasWriteContactsPermission) {
172158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesPermission(String8("android.permission.WRITE_CALL_LOG"));
172258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesImpliedPermission(String8("android.permission.WRITE_CALL_LOG"),
172358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                            String8("targetSdkVersion < 16 and requested WRITE_CONTACTS"));
1724282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1725282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1726282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1727282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            /* The following blocks handle printing "inferred" uses-features, based
1728282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             * on whether related features or permissions are used by the app.
1729282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             * Note that the various spec*Feature variables denote whether the
1730282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             * relevant tag was *present* in the AndroidManfest, not that it was
1731282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             * present and set to true.
1732282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             */
1733282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Camera-related back-compatibility logic
1734282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!specCameraFeature) {
1735282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (reqCameraFlashFeature) {
1736282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // if app requested a sub-feature (autofocus or flash) and didn't
1737282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // request the base camera feature, we infer that it meant to
1738282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    printf("uses-feature:'android.hardware.camera'\n");
1739282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    printf("uses-implied-feature:'android.hardware.camera'," \
1740282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            "'requested android.hardware.camera.flash feature'\n");
1741282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else if (reqCameraAutofocusFeature) {
1742282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // if app requested a sub-feature (autofocus or flash) and didn't
1743282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // request the base camera feature, we infer that it meant to
1744282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    printf("uses-feature:'android.hardware.camera'\n");
1745282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    printf("uses-implied-feature:'android.hardware.camera'," \
1746282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            "'requested android.hardware.camera.autofocus feature'\n");
1747282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else if (hasCameraPermission) {
17482675f769673f69b0661ddee346292f25cb30a296Maurice Chu                    // if app wants to use camera but didn't request the feature, we infer
1749282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // that it meant to, and further that it wants autofocus
1750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // (which was the 1.0 - 1.5 behavior)
1751282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    printf("uses-feature:'android.hardware.camera'\n");
1752282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (!specCameraAutofocusFeature) {
1753282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        printf("uses-feature:'android.hardware.camera.autofocus'\n");
1754282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        printf("uses-implied-feature:'android.hardware.camera.autofocus'," \
1755282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                "'requested android.permission.CAMERA permission'\n");
1756282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1757282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1758282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1759282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1760282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Location-related back-compatibility logic
1761282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!specLocationFeature &&
1762282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                (hasMockLocPermission || hasCoarseLocPermission || hasGpsPermission ||
1763282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 hasGeneralLocPermission || reqNetworkLocFeature || reqGpsFeature)) {
1764282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // if app either takes a location-related permission or requests one of the
1765282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // sub-features, we infer that it also meant to request the base location feature
1766282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("uses-feature:'android.hardware.location'\n");
1767282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("uses-implied-feature:'android.hardware.location'," \
1768282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "'requested a location access permission'\n");
1769282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1770282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!specGpsFeature && hasGpsPermission) {
1771282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // if app takes GPS (FINE location) perm but does not request the GPS
1772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // feature, we infer that it meant to
1773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("uses-feature:'android.hardware.location.gps'\n");
1774282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("uses-implied-feature:'android.hardware.location.gps'," \
1775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "'requested android.permission.ACCESS_FINE_LOCATION permission'\n");
1776282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!specNetworkLocFeature && hasCoarseLocPermission) {
1778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // if app takes Network location (COARSE location) perm but does not request the
1779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // network location feature, we infer that it meant to
1780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("uses-feature:'android.hardware.location.network'\n");
1781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("uses-implied-feature:'android.hardware.location.network'," \
1782282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "'requested android.permission.ACCESS_COARSE_LOCATION permission'\n");
1783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1784282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Bluetooth-related compatibility logic
1786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!specBluetoothFeature && hasBluetoothPermission && (targetSdk > 4)) {
1787282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // if app takes a Bluetooth permission but does not request the Bluetooth
1788282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // feature, we infer that it meant to
1789282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("uses-feature:'android.hardware.bluetooth'\n");
1790282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("uses-implied-feature:'android.hardware.bluetooth'," \
1791282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "'requested android.permission.BLUETOOTH or android.permission.BLUETOOTH_ADMIN " \
1792282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "permission and targetSdkVersion > 4'\n");
1793282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1794282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1795282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Microphone-related compatibility logic
1796282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!specMicrophoneFeature && hasRecordAudioPermission) {
1797282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // if app takes the record-audio permission but does not request the microphone
1798282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // feature, we infer that it meant to
1799282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("uses-feature:'android.hardware.microphone'\n");
1800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("uses-implied-feature:'android.hardware.microphone'," \
1801282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "'requested android.permission.RECORD_AUDIO permission'\n");
1802282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1803282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1804282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // WiFi-related compatibility logic
1805282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!specWiFiFeature && hasWiFiPermission) {
1806282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // if app takes one of the WiFi permissions but does not request the WiFi
1807282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // feature, we infer that it meant to
1808282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("uses-feature:'android.hardware.wifi'\n");
1809282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("uses-implied-feature:'android.hardware.wifi'," \
1810282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "'requested android.permission.ACCESS_WIFI_STATE, " \
1811282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "android.permission.CHANGE_WIFI_STATE, or " \
1812282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "android.permission.CHANGE_WIFI_MULTICAST_STATE permission'\n");
1813282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1815282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Telephony-related compatibility logic
1816282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!specTelephonyFeature && (hasTelephonyPermission || reqTelephonySubFeature)) {
1817282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // if app takes one of the telephony permissions or requests a sub-feature but
1818282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // does not request the base telephony feature, we infer that it meant to
1819282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("uses-feature:'android.hardware.telephony'\n");
1820282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("uses-implied-feature:'android.hardware.telephony'," \
1821282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "'requested a telephony-related permission or feature'\n");
1822282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1823282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1824282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Touchscreen-related back-compatibility logic
1825282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!specTouchscreenFeature) { // not a typo!
1826282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // all apps are presumed to require a touchscreen, unless they explicitly say
1827282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // <uses-feature android:name="android.hardware.touchscreen" android:required="false"/>
1828282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Note that specTouchscreenFeature is true if the tag is present, regardless
1829282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // of whether its value is true or false, so this is safe
1830282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("uses-feature:'android.hardware.touchscreen'\n");
1831282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("uses-implied-feature:'android.hardware.touchscreen'," \
1832282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "'assumed you require a touch screen unless explicitly made optional'\n");
1833282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1834282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!specMultitouchFeature && reqDistinctMultitouchFeature) {
1835282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // if app takes one of the telephony permissions or requests a sub-feature but
1836282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // does not request the base telephony feature, we infer that it meant to
1837282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("uses-feature:'android.hardware.touchscreen.multitouch'\n");
1838282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("uses-implied-feature:'android.hardware.touchscreen.multitouch'," \
1839282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "'requested android.hardware.touchscreen.multitouch.distinct feature'\n");
1840282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1841282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Landscape/portrait-related compatibility logic
1843282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!specScreenLandscapeFeature && !specScreenPortraitFeature) {
1844282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // If the app has specified any activities in its manifest
1845282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // that request a specific orientation, then assume that
1846282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // orientation is required.
1847282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (reqScreenLandscapeFeature) {
1848282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    printf("uses-feature:'android.hardware.screen.landscape'\n");
1849282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    printf("uses-implied-feature:'android.hardware.screen.landscape'," \
1850282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            "'one or more activities have specified a landscape orientation'\n");
1851282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (reqScreenPortraitFeature) {
1853282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    printf("uses-feature:'android.hardware.screen.portrait'\n");
1854282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    printf("uses-implied-feature:'android.hardware.screen.portrait'," \
1855282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            "'one or more activities have specified a portrait orientation'\n");
1856282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1857282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1858282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1859282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (hasWidgetReceivers) {
18609d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("app-widget");
1861282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1862a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            if (hasDeviceAdminReceiver) {
18639d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("device-admin");
1864a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            }
1865282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (hasImeService) {
18669d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("ime");
1867282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1868282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (hasWallpaperService) {
18699d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("wallpaper");
1870282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1871a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            if (hasAccessibilityService) {
18729d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("accessibility");
1873a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            }
1874a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            if (hasPrintService) {
18759d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("print-service");
1876a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            }
187794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            if (hasPaymentService) {
18789d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("payment");
18799d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            }
18809d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            if (isSearchable) {
18819d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("search");
18829d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            }
18839d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            if (hasDocumentsProvider) {
18849d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("document-provider");
18859d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            }
18869d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            if (hasLauncher) {
18879d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("launcher");
18889d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            }
18899d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            if (hasNotificationListenerService) {
18909d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("notification-listener");
18919d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            }
18929d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            if (hasCameraActivity) {
18939d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("camera");
18949d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            }
18959d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            if (hasCameraSecureActivity) {
18969d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("camera-secure");
18979d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            }
18989d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski
18999d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            if (hasMainActivity) {
19009d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printf("main\n");
190194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            }
1902282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (hasOtherActivities) {
1903282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("other-activities\n");
1904282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
19059d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski             if (hasOtherReceivers) {
1906282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("other-receivers\n");
1907282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1908282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (hasOtherServices) {
1909282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("other-services\n");
1910282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1911282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1912282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // For modern apps, if screen size buckets haven't been specified
1913282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // but the new width ranges have, then infer the buckets from them.
1914282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (smallScreen > 0 && normalScreen > 0 && largeScreen > 0 && xlargeScreen > 0
1915282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    && requiresSmallestWidthDp > 0) {
1916282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                int compatWidth = compatibleWidthLimitDp;
1917282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (compatWidth <= 0) {
1918282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    compatWidth = requiresSmallestWidthDp;
1919282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1920282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (requiresSmallestWidthDp <= 240 && compatWidth >= 240) {
1921282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    smallScreen = -1;
1922282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1923282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    smallScreen = 0;
1924282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1925282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (requiresSmallestWidthDp <= 320 && compatWidth >= 320) {
1926282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    normalScreen = -1;
1927282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1928282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    normalScreen = 0;
1929282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1930282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (requiresSmallestWidthDp <= 480 && compatWidth >= 480) {
1931282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    largeScreen = -1;
1932282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1933282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    largeScreen = 0;
1934282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1935282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (requiresSmallestWidthDp <= 720 && compatWidth >= 720) {
1936282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    xlargeScreen = -1;
1937282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1938282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    xlargeScreen = 0;
1939282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1940282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1941282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1942282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Determine default values for any unspecified screen sizes,
1943282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // based on the target SDK of the package.  As of 4 (donut)
1944282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // the screen size support was introduced, so all default to
1945282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // enabled.
1946282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (smallScreen > 0) {
1947282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                smallScreen = targetSdk >= 4 ? -1 : 0;
1948282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1949282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (normalScreen > 0) {
1950282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                normalScreen = -1;
1951282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1952282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (largeScreen > 0) {
1953282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                largeScreen = targetSdk >= 4 ? -1 : 0;
1954282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1955282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (xlargeScreen > 0) {
1956282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Introduced in Gingerbread.
1957282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                xlargeScreen = targetSdk >= 9 ? -1 : 0;
1958282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1959282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (anyDensity > 0) {
1960282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                anyDensity = (targetSdk >= 4 || requiresSmallestWidthDp > 0
1961282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        || compatibleWidthLimitDp > 0) ? -1 : 0;
1962282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1963282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("supports-screens:");
1964282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (smallScreen != 0) {
1965282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf(" 'small'");
1966282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1967282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (normalScreen != 0) {
1968282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf(" 'normal'");
1969282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1970282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (largeScreen != 0) {
1971282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf(" 'large'");
1972282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1973282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (xlargeScreen != 0) {
1974282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf(" 'xlarge'");
1975282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1976282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("\n");
1977282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("supports-any-density: '%s'\n", anyDensity ? "true" : "false");
1978282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (requiresSmallestWidthDp > 0) {
1979282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("requires-smallest-width:'%d'\n", requiresSmallestWidthDp);
1980282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1981282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (compatibleWidthLimitDp > 0) {
1982282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("compatible-width-limit:'%d'\n", compatibleWidthLimitDp);
1983282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1984282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (largestWidthLimitDp > 0) {
1985282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("largest-width-limit:'%d'\n", largestWidthLimitDp);
1986282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1987282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1988282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("locales:");
1989282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t NL = locales.size();
1990282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t i=0; i<NL; i++) {
1991282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                const char* localeStr =  locales[i].string();
1992282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (localeStr == NULL || strlen(localeStr) == 0) {
1993282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    localeStr = "--_--";
1994282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1995282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf(" '%s'", localeStr);
1996282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1997282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("\n");
1998282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1999282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("densities:");
2000282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t ND = densities.size();
2001282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t i=0; i<ND; i++) {
2002282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf(" '%d'", densities[i]);
2003282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2004282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("\n");
2005282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2006282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            AssetDir* dir = assets.openNonAssetDir(assetsCookie, "lib");
2007282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (dir != NULL) {
2008282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (dir->getFileCount() > 0) {
2009282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    printf("native-code:");
2010282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    for (size_t i=0; i<dir->getFileCount(); i++) {
20112675f769673f69b0661ddee346292f25cb30a296Maurice Chu                        printf(" '%s'", ResTable::normalizeForOutput(
20122675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                dir->getFileName(i).string()).string());
2013282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2014282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    printf("\n");
2015282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2016282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                delete dir;
2017282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2018282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else if (strcmp("badger", option) == 0) {
2019282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("%s", CONSOLE_DATA);
2020282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else if (strcmp("configurations", option) == 0) {
2021282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Vector<ResTable_config> configs;
2022282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            res.getConfigurations(&configs);
2023282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t N = configs.size();
2024282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t i=0; i<N; i++) {
2025282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("%s\n", configs[i].toString().string());
2026282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2027282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
2028282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: unknown dump option '%s'\n", option);
2029282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
2030282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2031282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2032282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2033282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    result = NO_ERROR;
2034282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2035282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail:
2036282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (asset) {
2037282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        delete asset;
2038282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2039282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return (result != NO_ERROR);
2040282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2041282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2042282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2043282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
2044282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Handle the "add" command, which wants to add files to a new or
2045282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * pre-existing archive.
2046282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
2047282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doAdd(Bundle* bundle)
2048282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2049282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ZipFile* zip = NULL;
2050282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t result = UNKNOWN_ERROR;
2051282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char* zipFileName;
2052282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2053282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getUpdate()) {
2054282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        /* avoid confusion */
2055282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: can't use '-u' with add\n");
2056282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2057282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2058282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2059282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getFileSpecCount() < 1) {
2060282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: must specify zip file name\n");
2061282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2062282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2063282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    zipFileName = bundle->getFileSpecEntry(0);
2064282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2065282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getFileSpecCount() < 2) {
2066282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "NOTE: nothing to do\n");
2067282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2068282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2069282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2070282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    zip = openReadWrite(zipFileName, true);
2071282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (zip == NULL) {
2072282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: failed opening/creating '%s' as Zip file\n", zipFileName);
2073282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2074282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2075282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2076282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (int i = 1; i < bundle->getFileSpecCount(); i++) {
2077282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const char* fileName = bundle->getFileSpecEntry(i);
2078282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2079282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (strcasecmp(String8(fileName).getPathExtension().string(), ".gz") == 0) {
2080282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf(" '%s'... (from gzip)\n", fileName);
2081282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            result = zip->addGzip(fileName, String8(fileName).getBasePath().string(), NULL);
2082282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
2083282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (bundle->getJunkPath()) {
2084282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String8 storageName = String8(fileName).getPathLeaf();
20852675f769673f69b0661ddee346292f25cb30a296Maurice Chu                printf(" '%s' as '%s'...\n", fileName,
20862675f769673f69b0661ddee346292f25cb30a296Maurice Chu                        ResTable::normalizeForOutput(storageName.string()).string());
2087282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                result = zip->add(fileName, storageName.string(),
2088282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  bundle->getCompressionMethod(), NULL);
2089282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
2090282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf(" '%s'...\n", fileName);
2091282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                result = zip->add(fileName, bundle->getCompressionMethod(), NULL);
2092282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2093282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2094282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (result != NO_ERROR) {
2095282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "Unable to add '%s' to '%s'", bundle->getFileSpecEntry(i), zipFileName);
2096282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (result == NAME_NOT_FOUND) {
2097282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, ": file not found\n");
2098282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (result == ALREADY_EXISTS) {
2099282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, ": already exists in archive\n");
2100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
2101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, "\n");
2102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
2104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    result = NO_ERROR;
2108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail:
2110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    delete zip;
2111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return (result != NO_ERROR);
2112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
2116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Delete files from an existing archive.
2117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
2118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doRemove(Bundle* bundle)
2119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ZipFile* zip = NULL;
2121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t result = UNKNOWN_ERROR;
2122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char* zipFileName;
2123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getFileSpecCount() < 1) {
2125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: must specify zip file name\n");
2126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    zipFileName = bundle->getFileSpecEntry(0);
2129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getFileSpecCount() < 2) {
2131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "NOTE: nothing to do\n");
2132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    zip = openReadWrite(zipFileName, false);
2136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (zip == NULL) {
2137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: failed opening Zip archive '%s'\n",
2138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            zipFileName);
2139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (int i = 1; i < bundle->getFileSpecCount(); i++) {
2143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const char* fileName = bundle->getFileSpecEntry(i);
2144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ZipEntry* entry;
2145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        entry = zip->getEntryByName(fileName);
2147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (entry == NULL) {
2148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf(" '%s' NOT FOUND\n", fileName);
2149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
2150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        result = zip->remove(entry);
2153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (result != NO_ERROR) {
2155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "Unable to delete '%s' from '%s'\n",
2156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                bundle->getFileSpecEntry(i), zipFileName);
2157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
2158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /* update the archive */
2162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    zip->flush();
2163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail:
2165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    delete zip;
2166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return (result != NO_ERROR);
2167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
21693921e87e6e67a063caa1987937d7944b24aef489Adam Lesinskistatic status_t addResourcesToBuilder(const sp<AaptDir>& dir, const sp<ApkBuilder>& builder, bool ignoreConfig=false) {
2170fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    const size_t numDirs = dir->getDirs().size();
2171fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    for (size_t i = 0; i < numDirs; i++) {
21723921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski        bool ignore = ignoreConfig;
21733921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski        const sp<AaptDir>& subDir = dir->getDirs().valueAt(i);
21743921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski        const char* dirStr = subDir->getLeaf().string();
21753921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski        if (!ignore && strstr(dirStr, "mipmap") == dirStr) {
21763921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski            ignore = true;
21773921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski        }
21783921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski        status_t err = addResourcesToBuilder(subDir, builder, ignore);
2179fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        if (err != NO_ERROR) {
2180fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            return err;
2181fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        }
2182fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    }
2183fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski
2184fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    const size_t numFiles = dir->getFiles().size();
2185fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    for (size_t i = 0; i < numFiles; i++) {
2186fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        sp<AaptGroup> gp = dir->getFiles().valueAt(i);
2187fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        const size_t numConfigs = gp->getFiles().size();
2188fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        for (size_t j = 0; j < numConfigs; j++) {
21893921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski            status_t err = NO_ERROR;
21903921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski            if (ignoreConfig) {
21913921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski                err = builder->getBaseSplit()->addEntry(gp->getPath(), gp->getFiles().valueAt(j));
21923921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski            } else {
21933921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski                err = builder->addEntry(gp->getPath(), gp->getFiles().valueAt(j));
21943921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski            }
2195fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            if (err != NO_ERROR) {
2196fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                fprintf(stderr, "Failed to add %s (%s) to builder.\n",
2197fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                        gp->getPath().string(), gp->getFiles()[j]->getPrintableSource().string());
2198fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                return err;
2199fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            }
2200fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        }
2201fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    }
2202fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    return NO_ERROR;
2203fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski}
2204fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski
2205fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinskistatic String8 buildApkName(const String8& original, const sp<ApkSplit>& split) {
2206fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (split->isBase()) {
2207fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        return original;
2208fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    }
2209fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski
2210fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    String8 ext(original.getPathExtension());
2211fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (ext == String8(".apk")) {
2212fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        return String8::format("%s_%s%s",
2213fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                original.getBasePath().string(),
2214fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                split->getDirectorySafeName().string(),
2215fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                ext.string());
2216fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    }
2217fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski
2218fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    return String8::format("%s_%s", original.string(),
2219fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            split->getDirectorySafeName().string());
2220fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski}
2221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
2223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Package up an asset directory and associated application files.
2224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
2225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doPackage(Bundle* bundle)
2226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char* outputAPKFile;
2228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int retVal = 1;
2229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err;
2230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<AaptAssets> assets;
2231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int N;
2232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    FILE* fp;
2233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String8 dependencyFile;
2234fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    sp<ApkBuilder> builder;
2235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2236a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin    // -c en_XA or/and ar_XB means do pseudolocalization
2237fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    sp<WeakResourceFilter> configFilter = new WeakResourceFilter();
2238fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    err = configFilter->parse(bundle->getConfigurations());
2239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
2240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2242fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (configFilter->containsPseudo()) {
2243a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        bundle->setPseudolocalize(bundle->getPseudolocalize() | PSEUDO_ACCENTED);
2244a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin    }
2245fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (configFilter->containsPseudoBidi()) {
2246a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        bundle->setPseudolocalize(bundle->getPseudolocalize() | PSEUDO_BIDI);
2247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    N = bundle->getFileSpecCount();
2250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (N < 1 && bundle->getResourceSourceDirs().size() == 0 && bundle->getJarFiles().size() == 0
225109384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski            && bundle->getAndroidManifestFile() == NULL && bundle->getAssetSourceDirs().size() == 0) {
2252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: no input files\n");
2253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    outputAPKFile = bundle->getOutputAPKFile();
2257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Make sure the filenames provided exist and are of the appropriate type.
2259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (outputAPKFile) {
2260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        FileType type;
2261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        type = getFileType(outputAPKFile);
2262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (type != kFileTypeNonexistent && type != kFileTypeRegular) {
2263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr,
2264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                "ERROR: output file '%s' exists but is not regular file\n",
2265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                outputAPKFile);
2266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
2267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Load the assets.
2271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    assets = new AaptAssets();
2272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Set up the resource gathering in assets if we're going to generate
2274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // dependency files. Every time we encounter a resource while slurping
2275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // the tree, we'll add it to these stores so we have full resource paths
2276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // to write to a dependency file.
2277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getGenDependencies()) {
2278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<FilePathStore> resPathStore = new FilePathStore;
2279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        assets->setFullResPaths(resPathStore);
2280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<FilePathStore> assetPathStore = new FilePathStore;
2281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        assets->setFullAssetPaths(assetPathStore);
2282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    err = assets->slurpFromArgs(bundle);
2285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err < 0) {
2286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getVerbose()) {
2290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        assets->print(String8());
2291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2293fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    // Create the ApkBuilder, which will collect the compiled files
2294fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    // to write to the final APK (or sets of APKs if we are building
2295fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    // a Split APK.
2296fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    builder = new ApkBuilder(configFilter);
2297fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski
2298fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    // If we are generating a Split APK, find out which configurations to split on.
2299fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (bundle->getSplitConfigurations().size() > 0) {
2300fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        const Vector<String8>& splitStrs = bundle->getSplitConfigurations();
2301fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        const size_t numSplits = splitStrs.size();
2302fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        for (size_t i = 0; i < numSplits; i++) {
2303fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            std::set<ConfigDescription> configs;
2304fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            if (!AaptConfig::parseCommaSeparatedList(splitStrs[i], &configs)) {
2305fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                fprintf(stderr, "ERROR: failed to parse split configuration '%s'\n", splitStrs[i].string());
2306fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                goto bail;
2307fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            }
2308fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski
2309fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            err = builder->createSplitForConfigs(configs);
2310fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            if (err != NO_ERROR) {
2311fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                goto bail;
2312fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            }
2313fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        }
2314fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    }
2315fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski
2316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // If they asked for any fileAs that need to be compiled, do so.
2317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getResourceSourceDirs().size() || bundle->getAndroidManifestFile()) {
2318fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        err = buildResources(bundle, assets, builder);
2319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != 0) {
2320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
2321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // At this point we've read everything and processed everything.  From here
2325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // on out it's just writing output files.
2326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (SourcePos::hasErrors()) {
2327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Update symbols with information about which ones are needed as Java symbols.
2331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    assets->applyJavaSymbols();
2332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (SourcePos::hasErrors()) {
2333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // If we've been asked to generate a dependency file, do that here
2337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getGenDependencies()) {
2338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // If this is the packaging step, generate the dependency file next to
2339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // the output apk (e.g. bin/resources.ap_.d)
2340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (outputAPKFile) {
2341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            dependencyFile = String8(outputAPKFile);
2342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Add the .d extension to the dependency file.
2343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            dependencyFile.append(".d");
2344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
2345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Else if this is the R.java dependency generation step,
2346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // generate the dependency file in the R.java package subdirectory
2347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // e.g. gen/com/foo/app/R.java.d
2348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            dependencyFile = String8(bundle->getRClassDir());
2349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            dependencyFile.appendPath("R.java.d");
2350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Make sure we have a clean dependency file to start with
2352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fp = fopen(dependencyFile, "w");
2353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fclose(fp);
2354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Write out R.java constants
2357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (!assets->havePrivateSymbols()) {
2358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (bundle->getCustomPackage() == NULL) {
2359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Write the R.java file into the appropriate class directory
2360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // e.g. gen/com/foo/app/R.java
2361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            err = writeResourceSymbols(bundle, assets, assets->getPackage(), true);
2362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
2363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const String8 customPkg(bundle->getCustomPackage());
2364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            err = writeResourceSymbols(bundle, assets, customPkg, true);
2365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err < 0) {
2367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
2368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // If we have library files, we're going to write our R.java file into
2370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // the appropriate class directory for those libraries as well.
2371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // e.g. gen/com/foo/app/lib/R.java
2372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (bundle->getExtraPackages() != NULL) {
2373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Split on colon
2374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 libs(bundle->getExtraPackages());
2375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            char* packageString = strtok(libs.lockBuffer(libs.length()), ":");
2376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            while (packageString != NULL) {
2377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Write the R.java file out with the correct package name
2378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                err = writeResourceSymbols(bundle, assets, String8(packageString), true);
2379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (err < 0) {
2380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    goto bail;
2381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                packageString = strtok(NULL, ":");
2383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            libs.unlockBuffer();
2385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
2387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        err = writeResourceSymbols(bundle, assets, assets->getPackage(), false);
2388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err < 0) {
2389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
2390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        err = writeResourceSymbols(bundle, assets, assets->getSymbolsPrivatePackage(), true);
2392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err < 0) {
2393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
2394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2397282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Write out the ProGuard file
2398282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    err = writeProguardFile(bundle, assets);
2399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err < 0) {
2400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Write the apk
2404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (outputAPKFile) {
2405fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        // Gather all resources and add them to the APK Builder. The builder will then
2406fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        // figure out which Split they belong in.
2407fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        err = addResourcesToBuilder(assets, builder);
2408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != NO_ERROR) {
2409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
2410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2411fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski
2412fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        const Vector<sp<ApkSplit> >& splits = builder->getSplits();
2413fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        const size_t numSplits = splits.size();
2414fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        for (size_t i = 0; i < numSplits; i++) {
2415fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            const sp<ApkSplit>& split = splits[i];
2416fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            String8 outputPath = buildApkName(String8(outputAPKFile), split);
2417fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            err = writeAPK(bundle, outputPath, split);
2418fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            if (err != NO_ERROR) {
2419fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                fprintf(stderr, "ERROR: packaging of '%s' failed\n", outputPath.string());
2420fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                goto bail;
2421fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            }
2422fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        }
2423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // If we've been asked to generate a dependency file, we need to finish up here.
2426282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // the writeResourceSymbols and writeAPK functions have already written the target
2427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // half of the dependency file, now we need to write the prerequisites. (files that
2428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // the R.java file or .ap_ file depend on)
2429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getGenDependencies()) {
2430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Now that writeResourceSymbols or writeAPK has taken care of writing
2431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // the targets to our dependency file, we'll write the prereqs
2432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fp = fopen(dependencyFile, "a+");
2433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(fp, " : ");
2434282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        bool includeRaw = (outputAPKFile != NULL);
2435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        err = writeDependencyPreReqs(bundle, assets, fp, includeRaw);
2436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Also manually add the AndroidManifeset since it's not under res/ or assets/
2437282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // and therefore was not added to our pathstores during slurping
2438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(fp, "%s \\\n", bundle->getAndroidManifestFile());
2439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fclose(fp);
2440282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2441282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    retVal = 0;
2443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail:
2444282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (SourcePos::hasErrors()) {
2445282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        SourcePos::printErrors(stderr);
2446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return retVal;
2448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
2451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Do PNG Crunching
2452282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * PRECONDITIONS
2453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *  -S flag points to a source directory containing drawable* folders
2454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *  -C flag points to destination directory. The folder structure in the
2455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *     source directory will be mirrored to the destination (cache) directory
2456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
2457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * POSTCONDITIONS
2458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *  Destination directory will be updated to match the PNG files in
24592675f769673f69b0661ddee346292f25cb30a296Maurice Chu *  the source directory.
2460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
2461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doCrunch(Bundle* bundle)
2462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(stdout, "Crunching PNG Files in ");
2464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(stdout, "source dir: %s\n", bundle->getResourceSourceDirs()[0]);
2465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(stdout, "To destination dir: %s\n", bundle->getCrunchedOutputDir());
2466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    updatePreProcessedCache(bundle);
2468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
2470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
2473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Do PNG Crunching on a single flag
2474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *  -i points to a single png file
2475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *  -o points to a single png output file
2476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
2477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doSingleCrunch(Bundle* bundle)
2478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2479282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(stdout, "Crunching single PNG file: %s\n", bundle->getSingleCrunchInputFile());
2480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(stdout, "\tOutput file: %s\n", bundle->getSingleCrunchOutputFile());
2481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String8 input(bundle->getSingleCrunchInputFile());
2483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String8 output(bundle->getSingleCrunchOutputFile());
2484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (preProcessImageToCache(bundle, input, output) != NO_ERROR) {
2486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // we can't return the status_t as it gets truncate to the lower 8 bits.
2487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return 42;
2488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
2491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskichar CONSOLE_DATA[2925] = {
2494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 95, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32,
2498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 63,
2499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    86, 35, 40, 46, 46, 95, 95, 95, 95, 97, 97, 44, 32, 46, 124, 42, 33, 83,
2500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    62, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 46, 58, 59, 61, 59, 61, 81,
2503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 66, 96, 61, 61, 58, 46, 46, 46, 58, 32, 32, 32, 32, 32, 32,
2504282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32,
2505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 46, 61, 59, 59, 59, 58, 106, 81, 81, 81, 81, 102, 59, 61, 59,
2507282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 61, 61, 61, 58, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2508282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2509282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59,
2510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 58, 109, 81, 81, 81, 81, 61, 59, 59, 59, 59, 59, 58, 59, 59, 46, 32,
2511282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2512282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2513282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 60, 81, 81, 81, 81, 87,
2514282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    58, 59, 59, 59, 59, 59, 59, 61, 119, 44, 32, 32, 32, 32, 32, 32, 32, 32,
2515282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32,
2516282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46,
2517282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    47, 61, 59, 59, 58, 100, 81, 81, 81, 81, 35, 58, 59, 59, 59, 59, 59, 58,
2518282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    121, 81, 91, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2519282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2520282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 109, 58, 59, 59, 61, 81, 81,
2521282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 109, 58, 59, 59, 59, 59, 61, 109, 81, 81, 76, 46, 32, 32, 32,
2522282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32,
2523282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2524282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 41, 87, 59, 61, 59, 41, 81, 81, 81, 81, 81, 81, 59, 61, 59,
2525282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 58, 109, 81, 81, 87, 39, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2526282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2527282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 60, 81, 91, 59,
2528282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 61, 81, 81, 81, 81, 81, 87, 43, 59, 58, 59, 60, 81, 81, 81, 76, 32,
2529282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2530282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2531282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 52, 91, 58, 45, 59, 87, 81, 81, 81, 81,
2532282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    70, 58, 58, 58, 59, 106, 81, 81, 81, 91, 32, 32, 32, 32, 32, 32, 32, 32,
2533282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32,
2534282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2535282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 93, 40, 32, 46, 59, 100, 81, 81, 81, 81, 40, 58, 46, 46, 58, 100, 81,
2536282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 68, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2537282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2538282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 46, 46, 46, 32, 46, 46, 46, 32, 46, 32, 46, 45, 91, 59, 61, 58, 109,
2539282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 87, 46, 58, 61, 59, 60, 81, 81, 80, 32, 32, 32, 32, 32, 32,
2540282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32,
2541282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 46, 46, 61, 59, 61, 61, 61, 59, 61, 61, 59,
2542282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 58, 58, 46, 46, 41, 58, 59, 58, 81, 81, 81, 81, 69, 58, 59, 59,
2543282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    60, 81, 81, 68, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2544282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 58, 59,
2545282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    61, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 61, 46,
2546282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    61, 59, 93, 81, 81, 81, 81, 107, 58, 59, 58, 109, 87, 68, 96, 32, 32, 32,
2547282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2548282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 10, 32, 32, 32, 46, 60, 61, 61, 59, 59, 59, 59, 59, 59, 59, 59,
2549282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 59, 59, 59, 59, 58, 58, 58, 115, 109, 68, 41, 36, 81,
2550282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    109, 46, 61, 61, 81, 69, 96, 46, 58, 58, 46, 58, 46, 46, 32, 32, 32, 32,
2551282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 46, 32, 95, 81,
2552282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    67, 61, 61, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
2553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 58, 68, 39, 61, 105, 61, 63, 81, 119, 58, 106, 80, 32, 58,
2554282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    61, 59, 59, 61, 59, 61, 59, 61, 46, 95, 32, 32, 32, 32, 32, 32, 32, 32,
2555282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 10, 32, 32, 36, 81, 109, 105, 59, 61, 59, 59, 59,
2556282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 46, 58, 37,
2557282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    73, 108, 108, 62, 52, 81, 109, 34, 32, 61, 59, 59, 59, 59, 59, 59, 59, 59,
2558282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 61, 59, 61, 61, 46, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10,
2559282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 46, 45, 57, 101, 43, 43, 61, 61, 59, 59, 59, 59, 59, 59, 61, 59, 59,
2560282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 59, 59, 58, 97, 46, 61, 108, 62, 126, 58, 106, 80, 96,
2561282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    46, 61, 61, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 61,
2562282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    97, 103, 97, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 45, 46, 32,
2563282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    46, 32, 32, 32, 32, 32, 32, 32, 32, 45, 45, 45, 58, 59, 59, 59, 59, 61,
2564282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    119, 81, 97, 124, 105, 124, 124, 39, 126, 95, 119, 58, 61, 58, 59, 59, 59,
2565282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 119, 81, 81, 99, 32, 32,
2566282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2567282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 58, 59, 59, 58, 106, 81, 81, 81, 109, 119,
2568282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    119, 119, 109, 109, 81, 81, 122, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59,
2569282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 58, 115, 81, 87, 81, 102, 32, 32, 32, 32, 32, 32, 10,
2570282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2571282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 61, 58, 59, 61, 81, 81, 81, 81, 81, 81, 87, 87, 81, 81, 81, 81,
2572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 58, 59, 59, 59, 59, 59, 59, 59, 59, 58, 45, 45, 45, 59, 59, 59, 41,
2573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    87, 66, 33, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32,
2574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 59, 59, 93, 81,
2575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 40, 58, 59, 59, 59, 58,
2576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    45, 32, 46, 32, 32, 32, 32, 32, 46, 32, 126, 96, 32, 32, 32, 32, 32, 32,
2577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 58, 61, 59, 58, 81, 81, 81, 81, 81, 81, 81, 81,
2579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 81, 81, 40, 58, 59, 59, 59, 58, 32, 32, 32, 32, 32, 32, 32,
2580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32,
2581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58,
2582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 58, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 40, 58,
2583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 46, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 59, 60, 81, 81, 81, 81,
2586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 81, 81, 81, 81, 81, 81, 59, 61, 59, 59, 61, 32, 32, 32, 32,
2587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 58, 59, 59, 93, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
2590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 40, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32,
2592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 58, 106,
2593282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 76, 58, 59, 59, 59,
2594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 61, 58, 58, 81, 81, 81, 81, 81, 81, 81, 81,
2597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 81, 81, 87, 58, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32,
2598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32,
2599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    58, 59, 61, 41, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 87, 59,
2601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    61, 58, 59, 59, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 58, 61, 81, 81, 81,
2604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 81, 81, 81, 81, 81, 81, 107, 58, 59, 59, 59, 59, 58, 32, 32,
2605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 58, 59, 59, 58, 51, 81, 81, 81, 81, 81, 81, 81, 81, 81,
2608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 102, 94, 59, 59, 59, 59, 59, 61, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32,
2610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 59,
2611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 43, 63, 36, 81, 81, 81, 87, 64, 86, 102, 58, 59, 59, 59, 59, 59,
2612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 59, 59, 59, 59, 43, 33,
2615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    58, 126, 126, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 32, 46, 32, 32,
2616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32,
2617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46,
2618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    61, 59, 59, 59, 58, 45, 58, 61, 59, 58, 58, 58, 61, 59, 59, 59, 59, 59,
2619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 59, 59, 58, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32,
2620282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32,
2621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 59, 59, 58, 95,
2622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 45, 61, 59, 61, 59, 59, 59, 59, 59, 59, 59, 45, 58, 59, 59, 59, 59,
2623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    61, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 58, 61, 59, 59, 59, 59, 59, 61, 59, 61, 46, 46, 32, 45, 45, 45,
2626282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 58, 45, 45, 46, 58, 59, 59, 59, 59, 59, 59, 61, 46, 32, 32, 32, 32,
2627282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32,
2628282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 58, 59, 59, 59, 59,
2629282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 61, 59, 46, 32, 32, 46, 32, 46, 32, 58, 61, 59, 59,
2630282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 59, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2631282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2632282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 45, 59, 59, 59, 59, 59, 59, 59, 59, 58, 32,
2633282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59, 59, 58, 32,
2634282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10,
2635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    46, 61, 59, 59, 59, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 61,
2637282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    46, 61, 59, 59, 59, 59, 59, 59, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32,
2639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59,
2640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 32, 46, 61, 58, 59, 59, 59, 59,
2641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 58, 59, 59, 59, 59, 59, 59, 59, 59, 46, 46, 32, 32, 32,
2644282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59, 59, 45, 32, 32, 32, 32, 32,
2645282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32,
2646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 32, 45, 61,
2647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 58, 32, 46, 32, 32, 32, 32, 32, 32, 32, 58, 59, 59,
2648282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 58, 45, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 45, 45, 45, 45, 32, 46, 32,
2651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 45, 61, 59, 58, 45, 45, 32, 32, 32,
2652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 46, 32, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10
2657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski  };
2658