Command.cpp revision 9eaaaf0fe3917f4fec85d3e45da37914654847ec
1282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//
2282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// Copyright 2006 The Android Open Source Project
3282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//
4282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// Android Asset Packaging Tool main entry point.
5282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//
6282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "Main.h"
7282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "Bundle.h"
8282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "ResourceFilter.h"
9282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "ResourceTable.h"
10282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "Images.h"
11282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "XMLNode.h"
12282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
13282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <utils/Log.h>
14282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <utils/threads.h>
15282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <utils/List.h>
16282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <utils/Errors.h>
17282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
18282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <fcntl.h>
19282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <errno.h>
20282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
21282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiusing namespace android;
22282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
23282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
24282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Show version info.  All the cool kids do it.
25282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
26282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doVersion(Bundle* bundle)
27282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
28282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getFileSpecCount() != 0) {
29282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printf("(ignoring extra arguments)\n");
30282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
31282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    printf("Android Asset Packaging Tool, v0.2\n");
32282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
33282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return 0;
34282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
35282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
36282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
37282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
38282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Open the file read only.  The call fails if the file doesn't exist.
39282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
40282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Returns NULL on failure.
41282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
42282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiZipFile* openReadOnly(const char* fileName)
43282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
44282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ZipFile* zip;
45282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t result;
46282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
47282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    zip = new ZipFile;
48282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    result = zip->open(fileName, ZipFile::kOpenReadOnly);
49282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (result != NO_ERROR) {
50282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (result == NAME_NOT_FOUND) {
51282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: '%s' not found\n", fileName);
52282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else if (result == PERMISSION_DENIED) {
53282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: '%s' access denied\n", fileName);
54282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
55282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: failed opening '%s' as Zip file\n",
56282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fileName);
57282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
58282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        delete zip;
59282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NULL;
60282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
61282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
62282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return zip;
63282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
64282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
65282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
66282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Open the file read-write.  The file will be created if it doesn't
67282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * already exist and "okayToCreate" is set.
68282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
69282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Returns NULL on failure.
70282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
71282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiZipFile* openReadWrite(const char* fileName, bool okayToCreate)
72282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
73282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ZipFile* zip = NULL;
74282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t result;
75282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int flags;
76282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
77282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    flags = ZipFile::kOpenReadWrite;
78282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (okayToCreate) {
79282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        flags |= ZipFile::kOpenCreate;
80282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
81282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
82282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    zip = new ZipFile;
83282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    result = zip->open(fileName, flags);
84282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (result != NO_ERROR) {
85282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        delete zip;
86282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        zip = NULL;
87282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
88282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
89282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
90282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail:
91282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return zip;
92282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
93282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
94282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
95282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
96282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Return a short string describing the compression method.
97282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
98282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiconst char* compressionName(int method)
99282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (method == ZipEntry::kCompressStored) {
101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return "Stored";
102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else if (method == ZipEntry::kCompressDeflated) {
103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return "Deflated";
104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return "Unknown";
106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Return the percent reduction in size (0% == no compression).
111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint calcPercent(long uncompressedLen, long compressedLen)
113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (!uncompressedLen) {
115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return 0;
116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return (int) (100.0 - (compressedLen * 100.0) / uncompressedLen + 0.5);
118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Handle the "list" command, which can be a simple file dump or
123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * a verbose listing.
124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * The verbose listing closely matches the output of the Info-ZIP "unzip"
126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * command.
127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doList(Bundle* bundle)
129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int result = 1;
131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ZipFile* zip = NULL;
132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const ZipEntry* entry;
133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    long totalUncLen, totalCompLen;
134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char* zipFileName;
135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getFileSpecCount() != 1) {
137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: specify zip file name (only)\n");
138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    zipFileName = bundle->getFileSpecEntry(0);
141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    zip = openReadOnly(zipFileName);
143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (zip == NULL) {
144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int count, i;
148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getVerbose()) {
150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printf("Archive:  %s\n", zipFileName);
151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printf(
152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            " Length   Method    Size  Ratio   Offset      Date  Time  CRC-32    Name\n");
153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printf(
154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            "--------  ------  ------- -----  -------      ----  ----  ------    ----\n");
155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    totalUncLen = totalCompLen = 0;
158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    count = zip->getNumEntries();
160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (i = 0; i < count; i++) {
161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        entry = zip->getEntryByIndex(i);
162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (bundle->getVerbose()) {
163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            char dateBuf[32];
164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            time_t when;
165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            when = entry->getModWhen();
167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            strftime(dateBuf, sizeof(dateBuf), "%m-%d-%y %H:%M",
168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                localtime(&when));
169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("%8ld  %-7.7s %7ld %3d%%  %8zd  %s  %08lx  %s\n",
171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                (long) entry->getUncompressedLen(),
172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                compressionName(entry->getCompressionMethod()),
173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                (long) entry->getCompressedLen(),
174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                calcPercent(entry->getUncompressedLen(),
175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            entry->getCompressedLen()),
176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                (size_t) entry->getLFHOffset(),
177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                dateBuf,
178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                entry->getCRC32(),
179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                entry->getFileName());
180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("%s\n", entry->getFileName());
182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        totalUncLen += entry->getUncompressedLen();
185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        totalCompLen += entry->getCompressedLen();
186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getVerbose()) {
189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printf(
190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        "--------          -------  ---                            -------\n");
191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printf("%8ld          %7ld  %2d%%                            %d files\n",
192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            totalUncLen,
193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            totalCompLen,
194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            calcPercent(totalUncLen, totalCompLen),
195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            zip->getNumEntries());
196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getAndroidList()) {
199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        AssetManager assets;
200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!assets.addAssetPath(String8(zipFileName), NULL)) {
201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: list -a failed because assets could not be loaded\n");
202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const ResTable& res = assets.getResources(false);
206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (&res == NULL) {
207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("\nNo resource table found.\n");
208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#ifndef HAVE_ANDROID_OS
210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("\nResource table:\n");
211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            res.print(false);
212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif
213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Asset* manifestAsset = assets.openNonAsset("AndroidManifest.xml",
216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                   Asset::ACCESS_BUFFER);
217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (manifestAsset == NULL) {
218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("\nNo AndroidManifest.xml found.\n");
219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("\nAndroid manifest:\n");
221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ResXMLTree tree;
222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            tree.setTo(manifestAsset->getBuffer(true),
223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       manifestAsset->getLength());
224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printXMLBlock(&tree);
225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        delete manifestAsset;
227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    result = 0;
230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail:
232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    delete zip;
233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return result;
234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic ssize_t indexOfAttribute(const ResXMLTree& tree, uint32_t attrRes)
237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t N = tree.getAttributeCount();
239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (size_t i=0; i<N; i++) {
240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (tree.getAttributeNameResID(i) == attrRes) {
241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return (ssize_t)i;
242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return -1;
245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
247282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiString8 getAttribute(const ResXMLTree& tree, const char* ns,
248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            const char* attr, String8* outError)
249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t idx = tree.indexOfAttribute(ns, attr);
251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (idx < 0) {
252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return String8();
253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Res_value value;
255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (value.dataType != Res_value::TYPE_STRING) {
257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (outError != NULL) {
258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                *outError = "attribute is not a string value";
259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return String8();
261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t len;
264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const uint16_t* str = tree.getAttributeStringValue(idx, &len);
265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return str ? String8(str, len) : String8();
266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic String8 getAttribute(const ResXMLTree& tree, uint32_t attrRes, String8* outError)
269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t idx = indexOfAttribute(tree, attrRes);
271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (idx < 0) {
272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return String8();
273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Res_value value;
275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (value.dataType != Res_value::TYPE_STRING) {
277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (outError != NULL) {
278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                *outError = "attribute is not a string value";
279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return String8();
281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t len;
284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const uint16_t* str = tree.getAttributeStringValue(idx, &len);
285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return str ? String8(str, len) : String8();
286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic int32_t getIntegerAttribute(const ResXMLTree& tree, uint32_t attrRes,
289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String8* outError, int32_t defValue = -1)
290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t idx = indexOfAttribute(tree, attrRes);
292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (idx < 0) {
293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return defValue;
294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Res_value value;
296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (value.dataType < Res_value::TYPE_FIRST_INT
298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                || value.dataType > Res_value::TYPE_LAST_INT) {
299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (outError != NULL) {
300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                *outError = "attribute is not an integer value";
301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return defValue;
303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return value.data;
306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic int32_t getResolvedIntegerAttribute(const ResTable* resTable, const ResXMLTree& tree,
309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        uint32_t attrRes, String8* outError, int32_t defValue = -1)
310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t idx = indexOfAttribute(tree, attrRes);
312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (idx < 0) {
313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return defValue;
314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Res_value value;
316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (value.dataType == Res_value::TYPE_REFERENCE) {
318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            resTable->resolveReference(&value, 0);
319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (value.dataType < Res_value::TYPE_FIRST_INT
321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                || value.dataType > Res_value::TYPE_LAST_INT) {
322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (outError != NULL) {
323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                *outError = "attribute is not an integer value";
324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return defValue;
326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return value.data;
329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic String8 getResolvedAttribute(const ResTable* resTable, const ResXMLTree& tree,
332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        uint32_t attrRes, String8* outError)
333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t idx = indexOfAttribute(tree, attrRes);
335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (idx < 0) {
336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return String8();
337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Res_value value;
339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (value.dataType == Res_value::TYPE_STRING) {
341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            size_t len;
342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const uint16_t* str = tree.getAttributeStringValue(idx, &len);
343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return str ? String8(str, len) : String8();
344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        resTable->resolveReference(&value, 0);
346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (value.dataType != Res_value::TYPE_STRING) {
347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (outError != NULL) {
348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                *outError = "attribute is not a string value";
349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return String8();
351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t len;
354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const Res_value* value2 = &value;
355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char16_t* str = const_cast<ResTable*>(resTable)->valueToString(value2, 0, NULL, &len);
356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return str ? String8(str, len) : String8();
357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic void getResolvedResourceAttribute(Res_value* value, const ResTable* resTable,
360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const ResXMLTree& tree, uint32_t attrRes, String8* outError)
361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t idx = indexOfAttribute(tree, attrRes);
363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (idx < 0) {
364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (outError != NULL) {
365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            *outError = "attribute could not be found";
366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return;
368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (tree.getAttributeValue(idx, value) != NO_ERROR) {
370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (value->dataType == Res_value::TYPE_REFERENCE) {
371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            resTable->resolveReference(value, 0);
372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // The attribute was found and was resolved if need be.
374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return;
375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (outError != NULL) {
377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        *outError = "error getting resolved resource attribute";
378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
38176327314d2238e105f8b94909f9c0cf85caca318Maurice Chustatic void printResolvedResourceAttribute(const ResTable* resTable, const ResXMLTree& tree,
38276327314d2238e105f8b94909f9c0cf85caca318Maurice Chu        uint32_t attrRes, String8 attrLabel, String8* outError)
38376327314d2238e105f8b94909f9c0cf85caca318Maurice Chu{
38476327314d2238e105f8b94909f9c0cf85caca318Maurice Chu    Res_value value;
38576327314d2238e105f8b94909f9c0cf85caca318Maurice Chu    getResolvedResourceAttribute(&value, resTable, tree, attrRes, outError);
38676327314d2238e105f8b94909f9c0cf85caca318Maurice Chu    if (*outError != "") {
38776327314d2238e105f8b94909f9c0cf85caca318Maurice Chu        *outError = "error print resolved resource attribute";
38876327314d2238e105f8b94909f9c0cf85caca318Maurice Chu        return;
38976327314d2238e105f8b94909f9c0cf85caca318Maurice Chu    }
39076327314d2238e105f8b94909f9c0cf85caca318Maurice Chu    if (value.dataType == Res_value::TYPE_STRING) {
39176327314d2238e105f8b94909f9c0cf85caca318Maurice Chu        String8 result = getResolvedAttribute(resTable, tree, attrRes, outError);
3922675f769673f69b0661ddee346292f25cb30a296Maurice Chu        printf("%s='%s'", attrLabel.string(),
3932675f769673f69b0661ddee346292f25cb30a296Maurice Chu                ResTable::normalizeForOutput(result.string()).string());
39476327314d2238e105f8b94909f9c0cf85caca318Maurice Chu    } else if (Res_value::TYPE_FIRST_INT <= value.dataType &&
39576327314d2238e105f8b94909f9c0cf85caca318Maurice Chu            value.dataType <= Res_value::TYPE_LAST_INT) {
39676327314d2238e105f8b94909f9c0cf85caca318Maurice Chu        printf("%s='%d'", attrLabel.string(), value.data);
39776327314d2238e105f8b94909f9c0cf85caca318Maurice Chu    } else {
39876327314d2238e105f8b94909f9c0cf85caca318Maurice Chu        printf("%s='0x%x'", attrLabel.string(), (int)value.data);
39976327314d2238e105f8b94909f9c0cf85caca318Maurice Chu    }
40076327314d2238e105f8b94909f9c0cf85caca318Maurice Chu}
40176327314d2238e105f8b94909f9c0cf85caca318Maurice Chu
402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// These are attribute resource constants for the platform, as found
403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// in android.R.attr
404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskienum {
405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    LABEL_ATTR = 0x01010001,
406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ICON_ATTR = 0x01010002,
407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    NAME_ATTR = 0x01010003,
408a5018c900f126ee8424c82497f32983873db741bAdam Lesinski    PERMISSION_ATTR = 0x01010006,
40994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    RESOURCE_ATTR = 0x01010025,
410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    DEBUGGABLE_ATTR = 0x0101000f,
411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    VALUE_ATTR = 0x01010024,
412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    VERSION_CODE_ATTR = 0x0101021b,
413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    VERSION_NAME_ATTR = 0x0101021c,
414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    SCREEN_ORIENTATION_ATTR = 0x0101001e,
415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    MIN_SDK_VERSION_ATTR = 0x0101020c,
416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    MAX_SDK_VERSION_ATTR = 0x01010271,
417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    REQ_TOUCH_SCREEN_ATTR = 0x01010227,
418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    REQ_KEYBOARD_TYPE_ATTR = 0x01010228,
419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    REQ_HARD_KEYBOARD_ATTR = 0x01010229,
420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    REQ_NAVIGATION_ATTR = 0x0101022a,
421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    REQ_FIVE_WAY_NAV_ATTR = 0x01010232,
422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    TARGET_SDK_VERSION_ATTR = 0x01010270,
423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    TEST_ONLY_ATTR = 0x01010272,
424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ANY_DENSITY_ATTR = 0x0101026c,
425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    GL_ES_VERSION_ATTR = 0x01010281,
426282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    SMALL_SCREEN_ATTR = 0x01010284,
427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    NORMAL_SCREEN_ATTR = 0x01010285,
428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    LARGE_SCREEN_ATTR = 0x01010286,
429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    XLARGE_SCREEN_ATTR = 0x010102bf,
430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    REQUIRED_ATTR = 0x0101028e,
431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    SCREEN_SIZE_ATTR = 0x010102ca,
432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    SCREEN_DENSITY_ATTR = 0x010102cb,
433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    REQUIRES_SMALLEST_WIDTH_DP_ATTR = 0x01010364,
434282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    COMPATIBLE_WIDTH_LIMIT_DP_ATTR = 0x01010365,
435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    LARGEST_WIDTH_LIMIT_DP_ATTR = 0x01010366,
436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    PUBLIC_KEY_ATTR = 0x010103a6,
43794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    CATEGORY_ATTR = 0x010103e8,
4380a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn    BANNER_ATTR = 0x10103f2,
439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski};
440282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4412675f769673f69b0661ddee346292f25cb30a296Maurice ChuString8 getComponentName(String8 &pkgName, String8 &componentName) {
442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t idx = componentName.find(".");
443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String8 retStr(pkgName);
444282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (idx == 0) {
445282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        retStr += componentName;
446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else if (idx < 0) {
447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        retStr += ".";
448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        retStr += componentName;
449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
4502675f769673f69b0661ddee346292f25cb30a296Maurice Chu        return componentName;
451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
4522675f769673f69b0661ddee346292f25cb30a296Maurice Chu    return retStr;
453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic void printCompatibleScreens(ResXMLTree& tree) {
456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t len;
457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ResXMLTree::event_code_t code;
458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int depth = 0;
459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool first = true;
460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    printf("compatible-screens:");
461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (code == ResXMLTree::END_TAG) {
463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            depth--;
464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (depth < 0) {
465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                break;
466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (code != ResXMLTree::START_TAG) {
470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        depth++;
473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String8 tag(tree.getElementName(&len));
474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (tag == "screen") {
475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int32_t screenSize = getIntegerAttribute(tree,
476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    SCREEN_SIZE_ATTR, NULL, -1);
477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int32_t screenDensity = getIntegerAttribute(tree,
478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    SCREEN_DENSITY_ATTR, NULL, -1);
479282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (screenSize > 0 && screenDensity > 0) {
480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!first) {
481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    printf(",");
482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                first = false;
484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("'%d/%d'", screenSize, screenDensity);
485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    printf("\n");
489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
49158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinskistatic void printUsesPermission(const String8& name, bool optional=false, int maxSdkVersion=-1) {
49258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski    printf("uses-permission: name='%s'", ResTable::normalizeForOutput(name.string()).string());
49358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski    if (maxSdkVersion != -1) {
49458f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski         printf(" maxSdkVersion='%d'", maxSdkVersion);
49558f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski    }
49658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski    printf("\n");
49758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski
49858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski    if (optional) {
49958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski        printf("optional-permission: name='%s'",
50058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                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}
50758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski
50858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinskistatic void printUsesImpliedPermission(const String8& name, const String8& reason) {
50958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski    printf("uses-implied-permission: name='%s' reason='%s'\n",
51058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski            ResTable::normalizeForOutput(name.string()).string(),
51158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski            ResTable::normalizeForOutput(reason.string()).string());
51258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski}
51358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski
51494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam LesinskiVector<String8> getNfcAidCategories(AssetManager& assets, String8 xmlPath, bool offHost,
51594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski        String8 *outError = NULL)
51694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski{
51794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    Asset* aidAsset = assets.openNonAsset(xmlPath, Asset::ACCESS_BUFFER);
51894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    if (aidAsset == NULL) {
51994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski        if (outError != NULL) *outError = "xml resource does not exist";
52094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski        return Vector<String8>();
52194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    }
52294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
52394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    const String8 serviceTagName(offHost ? "offhost-apdu-service" : "host-apdu-service");
52494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
52594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    bool withinApduService = false;
52694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    Vector<String8> categories;
52794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
52894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    String8 error;
52994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    ResXMLTree tree;
53094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    tree.setTo(aidAsset->getBuffer(true), aidAsset->getLength());
53194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
53294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    size_t len;
53394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    int depth = 0;
53494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    ResXMLTree::event_code_t code;
53594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
53694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski        if (code == ResXMLTree::END_TAG) {
53794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            depth--;
53894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            String8 tag(tree.getElementName(&len));
53994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
54094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            if (depth == 0 && tag == serviceTagName) {
54194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                withinApduService = false;
54294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            }
54394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
54494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski        } else if (code == ResXMLTree::START_TAG) {
54594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            depth++;
54694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            String8 tag(tree.getElementName(&len));
54794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
54894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            if (depth == 1) {
54994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                if (tag == serviceTagName) {
55094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    withinApduService = true;
55194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                }
55294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            } else if (depth == 2 && withinApduService) {
55394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                if (tag == "aid-group") {
55494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    String8 category = getAttribute(tree, CATEGORY_ATTR, &error);
55594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    if (error != "") {
55694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        if (outError != NULL) *outError = error;
55794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        return Vector<String8>();
55894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    }
55994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
56094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    categories.add(category);
56194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                }
56294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            }
56394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski        }
56494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    }
56594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    aidAsset->close();
56694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    return categories;
56794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski}
56894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
569282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
570282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Handle the "dump" command, to extract select data from an archive.
571282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiextern char CONSOLE_DATA[2925]; // see EOF
573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doDump(Bundle* bundle)
574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t result = UNKNOWN_ERROR;
576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Asset* asset = NULL;
577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getFileSpecCount() < 1) {
579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: no dump option specified\n");
580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return 1;
581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getFileSpecCount() < 2) {
584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: no dump file specified\n");
585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return 1;
586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char* option = bundle->getFileSpecEntry(0);
589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char* filename = bundle->getFileSpecEntry(1);
590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    AssetManager assets;
592f85e41f29a0e9313c2d4725f9d9648591ea49f3bNarayan Kamath    int32_t assetsCookie;
593282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (!assets.addAssetPath(String8(filename), &assetsCookie)) {
594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: dump failed because assets could not be loaded\n");
595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return 1;
596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Make a dummy config for retrieving resources...  we need to supply
599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // non-default values for some configs so that we can retrieve resources
600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // in the app that don't have a default.  The most important of these is
601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // the API version because key resources like icons will have an implicit
602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // version if they are using newer config types like density.
603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ResTable_config config;
60491447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath    memset(&config, 0, sizeof(ResTable_config));
605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    config.language[0] = 'e';
606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    config.language[1] = 'n';
607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    config.country[0] = 'U';
608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    config.country[1] = 'S';
609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    config.orientation = ResTable_config::ORIENTATION_PORT;
610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    config.density = ResTable_config::DENSITY_MEDIUM;
611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    config.sdkVersion = 10000; // Very high.
612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    config.screenWidthDp = 320;
613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    config.screenHeightDp = 480;
614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    config.smallestScreenWidthDp = 320;
615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    assets.setConfiguration(config);
616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const ResTable& res = assets.getResources(false);
618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (&res == NULL) {
619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: dump failed because no resource table was found\n");
620282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (strcmp("resources", option) == 0) {
624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#ifndef HAVE_ANDROID_OS
625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        res.print(bundle->getValues());
626282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif
627282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
628282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else if (strcmp("strings", option) == 0) {
629282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const ResStringPool* pool = res.getTableStringBlock(0);
630282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printStringPool(pool);
631282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
632282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else if (strcmp("xmltree", option) == 0) {
633282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (bundle->getFileSpecCount() < 3) {
634282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: no dump xmltree resource file specified\n");
635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
637282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (int i=2; i<bundle->getFileSpecCount(); i++) {
639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const char* resname = bundle->getFileSpecEntry(i);
640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ResXMLTree tree;
641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            asset = assets.openNonAsset(resname, Asset::ACCESS_BUFFER);
642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (asset == NULL) {
643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, "ERROR: dump failed because resource %s found\n", resname);
644282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                goto bail;
645282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (tree.setTo(asset->getBuffer(true),
648282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           asset->getLength()) != NO_ERROR) {
649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, "ERROR: Resource %s is corrupt\n", resname);
650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                goto bail;
651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            tree.restart();
653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printXMLBlock(&tree);
654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            tree.uninit();
655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            delete asset;
656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            asset = NULL;
657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else if (strcmp("xmlstrings", option) == 0) {
660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (bundle->getFileSpecCount() < 3) {
661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: no dump xmltree resource file specified\n");
662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (int i=2; i<bundle->getFileSpecCount(); i++) {
666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const char* resname = bundle->getFileSpecEntry(i);
667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ResXMLTree tree;
668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            asset = assets.openNonAsset(resname, Asset::ACCESS_BUFFER);
669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (asset == NULL) {
670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, "ERROR: dump failed because resource %s found\n", resname);
671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                goto bail;
672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (tree.setTo(asset->getBuffer(true),
675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           asset->getLength()) != NO_ERROR) {
676282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, "ERROR: Resource %s is corrupt\n", resname);
677282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                goto bail;
678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
679282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printStringPool(&tree.getStrings());
680282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            delete asset;
681282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            asset = NULL;
682282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
683282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
684282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
685282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ResXMLTree tree;
686282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        asset = assets.openNonAsset("AndroidManifest.xml",
687282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                            Asset::ACCESS_BUFFER);
688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (asset == NULL) {
689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: dump failed because no AndroidManifest.xml found\n");
690282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
691282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
692282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
693282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (tree.setTo(asset->getBuffer(true),
694282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       asset->getLength()) != NO_ERROR) {
695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: AndroidManifest.xml is corrupt\n");
696282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        tree.restart();
699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
700282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (strcmp("permissions", option) == 0) {
701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            size_t len;
702282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ResXMLTree::event_code_t code;
703282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int depth = 0;
704282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
705282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (code == ResXMLTree::END_TAG) {
706282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    depth--;
707282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
708282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
709282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (code != ResXMLTree::START_TAG) {
710282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
711282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                depth++;
713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String8 tag(tree.getElementName(&len));
714282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                //printf("Depth %d tag %s\n", depth, tag.string());
715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (depth == 1) {
716282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (tag != "manifest") {
717282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n");
718282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        goto bail;
719282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
720282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8 pkg = getAttribute(tree, NULL, "package", NULL);
7212675f769673f69b0661ddee346292f25cb30a296Maurice Chu                    printf("package: %s\n", ResTable::normalizeForOutput(pkg.string()).string());
722282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else if (depth == 2 && tag == "permission") {
723282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8 error;
724282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8 name = getAttribute(tree, NAME_ATTR, &error);
725282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (error != "") {
726282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        fprintf(stderr, "ERROR: %s\n", error.string());
727282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        goto bail;
728282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
7292675f769673f69b0661ddee346292f25cb30a296Maurice Chu                    printf("permission: %s\n",
7302675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            ResTable::normalizeForOutput(name.string()).string());
731282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else if (depth == 2 && tag == "uses-permission") {
732282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8 error;
733282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8 name = getAttribute(tree, NAME_ATTR, &error);
734282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (error != "") {
735282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        fprintf(stderr, "ERROR: %s\n", error.string());
736282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        goto bail;
737282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
73858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesPermission(name,
73958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                            getIntegerAttribute(tree, REQUIRED_ATTR, NULL, 1) == 0,
74058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                            getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR, NULL, -1));
741282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
742282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
743282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else if (strcmp("badging", option) == 0) {
744282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Vector<String8> locales;
745282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            res.getLocales(&locales);
746282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
747282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Vector<ResTable_config> configs;
748282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            res.getConfigurations(&configs);
749282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            SortedVector<int> densities;
750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t NC = configs.size();
751282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t i=0; i<NC; i++) {
752282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                int dens = configs[i].density;
753282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (dens == 0) {
754282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    dens = 160;
755282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
756282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                densities.add(dens);
757282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
758282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
759282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            size_t len;
760282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ResXMLTree::event_code_t code;
761282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int depth = 0;
762282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 error;
763282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool withinActivity = false;
764282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool isMainActivity = false;
765282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool isLauncherActivity = false;
7660a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn            bool isLeanbackLauncherActivity = false;
767282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool isSearchable = false;
768282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool withinApplication = false;
769ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright            bool withinSupportsInput = false;
770282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool withinReceiver = false;
771282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool withinService = false;
772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool withinIntentFilter = false;
773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasMainActivity = false;
774282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasOtherActivities = false;
775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasOtherReceivers = false;
776282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasOtherServices = false;
777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasWallpaperService = false;
778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasImeService = false;
779a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool hasAccessibilityService = false;
780a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool hasPrintService = false;
781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasWidgetReceivers = false;
782a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool hasDeviceAdminReceiver = false;
783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasIntentFilter = false;
78494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            bool hasPaymentService = false;
785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool actMainActivity = false;
786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool actWidgetReceivers = false;
787a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool actDeviceAdminEnabled = false;
788282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool actImeService = false;
789282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool actWallpaperService = false;
790a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool actAccessibilityService = false;
791a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool actPrintService = false;
79294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            bool actHostApduService = false;
79394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            bool actOffHostApduService = false;
79494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            bool hasMetaHostPaymentCategory = false;
79594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            bool hasMetaOffHostPaymentCategory = false;
796a5018c900f126ee8424c82497f32983873db741bAdam Lesinski
797a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            // These permissions are required by services implementing services
798a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            // the system binds to (IME, Accessibility, PrintServices, etc.)
799a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool hasBindDeviceAdminPermission = false;
800a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool hasBindInputMethodPermission = false;
801a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool hasBindAccessibilityServicePermission = false;
802a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool hasBindPrintServicePermission = false;
80394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            bool hasBindNfcServicePermission = false;
804282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
805282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // These two implement the implicit permissions that are granted
806282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // to pre-1.6 applications.
807282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasWriteExternalStoragePermission = false;
808282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasReadPhoneStatePermission = false;
809282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
810282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // If an app requests write storage, they will also get read storage.
811282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasReadExternalStoragePermission = false;
812282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
813282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Implement transition to read and write call log.
814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasReadContactsPermission = false;
815282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasWriteContactsPermission = false;
816282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasReadCallLogPermission = false;
817282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasWriteCallLogPermission = false;
818282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
819282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // This next group of variables is used to implement a group of
820282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // backward-compatibility heuristics necessitated by the addition of
821282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // some new uses-feature constants in 2.1 and 2.2. In most cases, the
822282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // heuristic is "if an app requests a permission but doesn't explicitly
823282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // request the corresponding <uses-feature>, presume it's there anyway".
824282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool specCameraFeature = false; // camera-related
825282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool specCameraAutofocusFeature = false;
826282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool reqCameraAutofocusFeature = false;
827282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool reqCameraFlashFeature = false;
828282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasCameraPermission = false;
829282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool specLocationFeature = false; // location-related
830282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool specNetworkLocFeature = false;
831282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool reqNetworkLocFeature = false;
832282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool specGpsFeature = false;
833282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool reqGpsFeature = false;
834282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasMockLocPermission = false;
835282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasCoarseLocPermission = false;
836282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasGpsPermission = false;
837282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasGeneralLocPermission = false;
838282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool specBluetoothFeature = false; // Bluetooth API-related
839282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasBluetoothPermission = false;
840282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool specMicrophoneFeature = false; // microphone-related
841282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasRecordAudioPermission = false;
842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool specWiFiFeature = false;
843282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasWiFiPermission = false;
844282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool specTelephonyFeature = false; // telephony-related
845282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool reqTelephonySubFeature = false;
846282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasTelephonyPermission = false;
847282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool specTouchscreenFeature = false; // touchscreen-related
848282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool specMultitouchFeature = false;
849282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool reqDistinctMultitouchFeature = false;
850282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool specScreenPortraitFeature = false;
851282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool specScreenLandscapeFeature = false;
852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool reqScreenPortraitFeature = false;
853282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool reqScreenLandscapeFeature = false;
854282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // 2.2 also added some other features that apps can request, but that
855282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // have no corresponding permission, so we cannot implement any
856282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // back-compatibility heuristic for them. The below are thus unnecessary
857282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // (but are retained here for documentary purposes.)
858282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //bool specCompassFeature = false;
859282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //bool specAccelerometerFeature = false;
860282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //bool specProximityFeature = false;
861282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //bool specAmbientLightFeature = false;
862282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //bool specLiveWallpaperFeature = false;
863282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
864282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int targetSdk = 0;
865282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int smallScreen = 1;
866282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int normalScreen = 1;
867282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int largeScreen = 1;
868282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int xlargeScreen = 1;
869282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int anyDensity = 1;
870282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int requiresSmallestWidthDp = 0;
871282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int compatibleWidthLimitDp = 0;
872282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int largestWidthLimitDp = 0;
873282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 pkg;
874282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 activityName;
875282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 activityLabel;
876282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 activityIcon;
8770a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn            String8 activityBanner;
878282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 receiverName;
879282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 serviceName;
880ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright            Vector<String8> supportedInput;
881282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
882282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (code == ResXMLTree::END_TAG) {
883282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    depth--;
884282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (depth < 2) {
885ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        if (withinSupportsInput && !supportedInput.isEmpty()) {
886ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            printf("supports-input: '");
887ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            const size_t N = supportedInput.size();
888ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            for (size_t i=0; i<N; i++) {
8892675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                printf("%s", ResTable::normalizeForOutput(
8902675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                        supportedInput[i].string()).string());
891ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                if (i != N - 1) {
892ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                    printf("' '");
893ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                } else {
894ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                    printf("'\n");
895ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                }
896ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
897ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            supportedInput.clear();
898ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        }
899282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        withinApplication = false;
900ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        withinSupportsInput = false;
901282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (depth < 3) {
9020a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                        if (withinActivity && isMainActivity) {
9032675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            String8 aName(getComponentName(pkg, activityName));
9040a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                            if (isLauncherActivity) {
9050a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                printf("launchable-activity:");
9069eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                if (aName.length() > 0) {
9079eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                    printf(" name='%s' ",
9089eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                            ResTable::normalizeForOutput(aName.string()).string());
9090a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                }
9100a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                printf(" label='%s' icon='%s'\n",
9119eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                        ResTable::normalizeForOutput(activityLabel.string()).string(),
9129eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                        ResTable::normalizeForOutput(activityIcon.string()).string());
9130a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                            }
9140a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                            if (isLeanbackLauncherActivity) {
9150a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                printf("leanback-launchable-activity:");
9169eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                if (aName.length() > 0) {
9179eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                    printf(" name='%s' ",
9189eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                            ResTable::normalizeForOutput(aName.string()).string());
9190a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                }
9200a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                printf(" label='%s' icon='%s' banner='%s'\n",
9219eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                        ResTable::normalizeForOutput(activityLabel.string()).string(),
9229eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                        ResTable::normalizeForOutput(activityIcon.string()).string(),
9239eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                        ResTable::normalizeForOutput(activityBanner.string()).string());
924282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
925282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
926282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (!hasIntentFilter) {
927282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            hasOtherActivities |= withinActivity;
928282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            hasOtherReceivers |= withinReceiver;
929282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            hasOtherServices |= withinService;
93094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        } else {
93194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            if (withinService) {
93294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                hasPaymentService |= (actHostApduService && hasMetaHostPaymentCategory &&
93394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                        hasBindNfcServicePermission);
93494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                hasPaymentService |= (actOffHostApduService && hasMetaOffHostPaymentCategory &&
93594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                        hasBindNfcServicePermission);
93694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            }
937282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
938282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        withinActivity = false;
939282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        withinService = false;
940282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        withinReceiver = false;
941282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasIntentFilter = false;
9420a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                        isMainActivity = isLauncherActivity = isLeanbackLauncherActivity = false;
943282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (depth < 4) {
944282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (withinIntentFilter) {
945282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (withinActivity) {
946282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasMainActivity |= actMainActivity;
947282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasOtherActivities |= !actMainActivity;
948282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (withinReceiver) {
949282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasWidgetReceivers |= actWidgetReceivers;
950a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                hasDeviceAdminReceiver |= (actDeviceAdminEnabled &&
951a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                        hasBindDeviceAdminPermission);
952a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                hasOtherReceivers |= (!actWidgetReceivers && !actDeviceAdminEnabled);
953282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (withinService) {
954282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasImeService |= actImeService;
955282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasWallpaperService |= actWallpaperService;
956a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                hasAccessibilityService |= (actAccessibilityService &&
957a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                        hasBindAccessibilityServicePermission);
958a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                hasPrintService |= (actPrintService && hasBindPrintServicePermission);
959a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                hasOtherServices |= (!actImeService && !actWallpaperService &&
96094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                        !actAccessibilityService && !actPrintService &&
96194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                        !actHostApduService && !actOffHostApduService);
962282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
963282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
964282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        withinIntentFilter = false;
965282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
966282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
967282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
968282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (code != ResXMLTree::START_TAG) {
969282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
970282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
971282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                depth++;
972282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String8 tag(tree.getElementName(&len));
973282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                //printf("Depth %d,  %s\n", depth, tag.string());
974282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (depth == 1) {
975282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (tag != "manifest") {
976282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n");
977282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        goto bail;
978282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
979282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    pkg = getAttribute(tree, NULL, "package", NULL);
9802675f769673f69b0661ddee346292f25cb30a296Maurice Chu                    printf("package: name='%s' ",
9812675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            ResTable::normalizeForOutput(pkg.string()).string());
982282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    int32_t versionCode = getIntegerAttribute(tree, VERSION_CODE_ATTR, &error);
983282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (error != "") {
984282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        fprintf(stderr, "ERROR getting 'android:versionCode' attribute: %s\n", error.string());
985282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        goto bail;
986282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
987282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (versionCode > 0) {
988282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        printf("versionCode='%d' ", versionCode);
989282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else {
990282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        printf("versionCode='' ");
991282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
992282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8 versionName = getResolvedAttribute(&res, tree, VERSION_NAME_ATTR, &error);
993282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (error != "") {
994282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        fprintf(stderr, "ERROR getting 'android:versionName' attribute: %s\n", error.string());
995282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        goto bail;
996282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
9972675f769673f69b0661ddee346292f25cb30a296Maurice Chu                    printf("versionName='%s'\n",
9982675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            ResTable::normalizeForOutput(versionName.string()).string());
999282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else if (depth == 2) {
1000282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    withinApplication = false;
1001282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (tag == "application") {
1002282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        withinApplication = true;
1003282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1004282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8 label;
1005282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const size_t NL = locales.size();
1006282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        for (size_t i=0; i<NL; i++) {
1007282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            const char* localeStr =  locales[i].string();
1008282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            assets.setLocale(localeStr != NULL ? localeStr : "");
1009282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            String8 llabel = getResolvedAttribute(&res, tree, LABEL_ATTR, &error);
1010282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (llabel != "") {
1011282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                if (localeStr == NULL || strlen(localeStr) == 0) {
1012282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    label = llabel;
10132675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                    printf("application-label:'%s'\n",
10142675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                            ResTable::normalizeForOutput(llabel.string()).string());
1015282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                } else {
1016282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    if (label == "") {
1017282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        label = llabel;
1018282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    }
1019282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    printf("application-label-%s:'%s'\n", localeStr,
10202675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                           ResTable::normalizeForOutput(llabel.string()).string());
1021282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                }
1022282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1023282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1024282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1025282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ResTable_config tmpConfig = config;
1026282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const size_t ND = densities.size();
1027282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        for (size_t i=0; i<ND; i++) {
1028282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            tmpConfig.density = densities[i];
1029282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            assets.setConfiguration(tmpConfig);
1030282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            String8 icon = getResolvedAttribute(&res, tree, ICON_ATTR, &error);
1031282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (icon != "") {
10322675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                printf("application-icon-%d:'%s'\n", densities[i],
10332675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                        ResTable::normalizeForOutput(icon.string()).string());
1034282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1035282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1036282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        assets.setConfiguration(config);
1037282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1038282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8 icon = getResolvedAttribute(&res, tree, ICON_ATTR, &error);
1039282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (error != "") {
1040282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n", error.string());
1041282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            goto bail;
1042282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1043282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        int32_t testOnly = getIntegerAttribute(tree, TEST_ONLY_ATTR, &error, 0);
1044282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (error != "") {
1045282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            fprintf(stderr, "ERROR getting 'android:testOnly' attribute: %s\n", error.string());
1046282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            goto bail;
1047282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
10482675f769673f69b0661ddee346292f25cb30a296Maurice Chu                        printf("application: label='%s' ",
10492675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                ResTable::normalizeForOutput(label.string()).string());
10502675f769673f69b0661ddee346292f25cb30a296Maurice Chu                        printf("icon='%s'\n", ResTable::normalizeForOutput(icon.string()).string());
1051282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (testOnly != 0) {
1052282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf("testOnly='%d'\n", testOnly);
1053282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1054282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1055282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        int32_t debuggable = getResolvedIntegerAttribute(&res, tree, DEBUGGABLE_ATTR, &error, 0);
1056282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (error != "") {
1057282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            fprintf(stderr, "ERROR getting 'android:debuggable' attribute: %s\n", error.string());
1058282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            goto bail;
1059282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1060282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (debuggable != 0) {
1061282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf("application-debuggable\n");
1062282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1063282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "uses-sdk") {
1064282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        int32_t code = getIntegerAttribute(tree, MIN_SDK_VERSION_ATTR, &error);
1065282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (error != "") {
1066282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            error = "";
1067282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            String8 name = getResolvedAttribute(&res, tree, MIN_SDK_VERSION_ATTR, &error);
1068282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (error != "") {
1069282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                fprintf(stderr, "ERROR getting 'android:minSdkVersion' attribute: %s\n",
1070282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        error.string());
1071282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                goto bail;
1072282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1073282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (name == "Donut") targetSdk = 4;
10742675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            printf("sdkVersion:'%s'\n",
10752675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                    ResTable::normalizeForOutput(name.string()).string());
1076282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else if (code != -1) {
1077282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            targetSdk = code;
1078282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf("sdkVersion:'%d'\n", code);
1079282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1080282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        code = getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR, NULL, -1);
1081282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (code != -1) {
1082282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf("maxSdkVersion:'%d'\n", code);
1083282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1084282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        code = getIntegerAttribute(tree, TARGET_SDK_VERSION_ATTR, &error);
1085282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (error != "") {
1086282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            error = "";
1087282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            String8 name = getResolvedAttribute(&res, tree, TARGET_SDK_VERSION_ATTR, &error);
1088282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (error != "") {
1089282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                fprintf(stderr, "ERROR getting 'android:targetSdkVersion' attribute: %s\n",
1090282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        error.string());
1091282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                goto bail;
1092282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1093282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (name == "Donut" && targetSdk < 4) targetSdk = 4;
10942675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            printf("targetSdkVersion:'%s'\n",
10952675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                    ResTable::normalizeForOutput(name.string()).string());
1096282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else if (code != -1) {
1097282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (targetSdk < code) {
1098282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                targetSdk = code;
1099282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf("targetSdkVersion:'%d'\n", code);
1101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "uses-configuration") {
1103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        int32_t reqTouchScreen = getIntegerAttribute(tree,
1104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                REQ_TOUCH_SCREEN_ATTR, NULL, 0);
1105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        int32_t reqKeyboardType = getIntegerAttribute(tree,
1106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                REQ_KEYBOARD_TYPE_ATTR, NULL, 0);
1107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        int32_t reqHardKeyboard = getIntegerAttribute(tree,
1108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                REQ_HARD_KEYBOARD_ATTR, NULL, 0);
1109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        int32_t reqNavigation = getIntegerAttribute(tree,
1110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                REQ_NAVIGATION_ATTR, NULL, 0);
1111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        int32_t reqFiveWayNav = getIntegerAttribute(tree,
1112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                REQ_FIVE_WAY_NAV_ATTR, NULL, 0);
1113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        printf("uses-configuration:");
1114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (reqTouchScreen != 0) {
1115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf(" reqTouchScreen='%d'", reqTouchScreen);
1116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (reqKeyboardType != 0) {
1118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf(" reqKeyboardType='%d'", reqKeyboardType);
1119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (reqHardKeyboard != 0) {
1121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf(" reqHardKeyboard='%d'", reqHardKeyboard);
1122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (reqNavigation != 0) {
1124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf(" reqNavigation='%d'", reqNavigation);
1125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (reqFiveWayNav != 0) {
1127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf(" reqFiveWayNav='%d'", reqFiveWayNav);
1128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        printf("\n");
1130ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                    } else if (tag == "supports-input") {
1131ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        withinSupportsInput = true;
1132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "supports-screens") {
1133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        smallScreen = getIntegerAttribute(tree,
1134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                SMALL_SCREEN_ATTR, NULL, 1);
1135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        normalScreen = getIntegerAttribute(tree,
1136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                NORMAL_SCREEN_ATTR, NULL, 1);
1137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        largeScreen = getIntegerAttribute(tree,
1138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                LARGE_SCREEN_ATTR, NULL, 1);
1139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        xlargeScreen = getIntegerAttribute(tree,
1140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                XLARGE_SCREEN_ATTR, NULL, 1);
1141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        anyDensity = getIntegerAttribute(tree,
1142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                ANY_DENSITY_ATTR, NULL, 1);
1143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        requiresSmallestWidthDp = getIntegerAttribute(tree,
1144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                REQUIRES_SMALLEST_WIDTH_DP_ATTR, NULL, 0);
1145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        compatibleWidthLimitDp = getIntegerAttribute(tree,
1146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                COMPATIBLE_WIDTH_LIMIT_DP_ATTR, NULL, 0);
1147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        largestWidthLimitDp = getIntegerAttribute(tree,
1148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                LARGEST_WIDTH_LIMIT_DP_ATTR, NULL, 0);
1149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "uses-feature") {
1150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8 name = getAttribute(tree, NAME_ATTR, &error);
1151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (name != "" && error == "") {
1153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            int req = getIntegerAttribute(tree,
1154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    REQUIRED_ATTR, NULL, 1);
1155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (name == "android.hardware.camera") {
1157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                specCameraFeature = true;
1158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.hardware.camera.autofocus") {
1159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                // these have no corresponding permission to check for,
1160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                // but should imply the foundational camera permission
1161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                reqCameraAutofocusFeature = reqCameraAutofocusFeature || req;
1162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                specCameraAutofocusFeature = true;
1163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (req && (name == "android.hardware.camera.flash")) {
1164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                // these have no corresponding permission to check for,
1165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                // but should imply the foundational camera permission
1166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                reqCameraFlashFeature = true;
1167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.hardware.location") {
1168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                specLocationFeature = true;
1169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.hardware.location.network") {
1170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                specNetworkLocFeature = true;
1171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                reqNetworkLocFeature = reqNetworkLocFeature || req;
1172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.hardware.location.gps") {
1173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                specGpsFeature = true;
1174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                reqGpsFeature = reqGpsFeature || req;
1175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.hardware.bluetooth") {
1176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                specBluetoothFeature = true;
1177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.hardware.touchscreen") {
1178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                specTouchscreenFeature = true;
1179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.hardware.touchscreen.multitouch") {
1180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                specMultitouchFeature = true;
1181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.hardware.touchscreen.multitouch.distinct") {
1182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                reqDistinctMultitouchFeature = reqDistinctMultitouchFeature || req;
1183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.hardware.microphone") {
1184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                specMicrophoneFeature = true;
1185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.hardware.wifi") {
1186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                specWiFiFeature = true;
1187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.hardware.telephony") {
1188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                specTelephonyFeature = true;
1189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (req && (name == "android.hardware.telephony.gsm" ||
1190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                               name == "android.hardware.telephony.cdma")) {
1191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                // these have no corresponding permission to check for,
1192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                // but should imply the foundational telephony permission
1193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                reqTelephonySubFeature = true;
1194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.hardware.screen.portrait") {
1195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                specScreenPortraitFeature = true;
1196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.hardware.screen.landscape") {
1197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                specScreenLandscapeFeature = true;
1198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf("uses-feature%s:'%s'\n",
12002675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                    req ? "" : "-not-required",
12012675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                            ResTable::normalizeForOutput(name.string()).string());
1202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else {
1203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            int vers = getIntegerAttribute(tree,
1204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    GL_ES_VERSION_ATTR, &error);
1205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (error == "") {
1206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                printf("uses-gl-es:'0x%x'\n", vers);
1207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "uses-permission") {
1210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8 name = getAttribute(tree, NAME_ATTR, &error);
1211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (name != "" && error == "") {
1212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (name == "android.permission.CAMERA") {
1213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasCameraPermission = true;
1214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.ACCESS_FINE_LOCATION") {
1215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasGpsPermission = true;
1216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.ACCESS_MOCK_LOCATION") {
1217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasMockLocPermission = true;
1218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.ACCESS_COARSE_LOCATION") {
1219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasCoarseLocPermission = true;
1220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" ||
1221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.INSTALL_LOCATION_PROVIDER") {
1222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasGeneralLocPermission = true;
1223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.BLUETOOTH" ||
1224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.BLUETOOTH_ADMIN") {
1225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasBluetoothPermission = true;
1226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.RECORD_AUDIO") {
1227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasRecordAudioPermission = true;
1228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.ACCESS_WIFI_STATE" ||
1229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.CHANGE_WIFI_STATE" ||
1230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.CHANGE_WIFI_MULTICAST_STATE") {
1231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasWiFiPermission = true;
1232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.CALL_PHONE" ||
1233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.CALL_PRIVILEGED" ||
1234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.MODIFY_PHONE_STATE" ||
1235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.PROCESS_OUTGOING_CALLS" ||
1236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.READ_SMS" ||
1237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.RECEIVE_SMS" ||
1238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.RECEIVE_MMS" ||
1239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.RECEIVE_WAP_PUSH" ||
1240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.SEND_SMS" ||
1241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.WRITE_APN_SETTINGS" ||
1242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.WRITE_SMS") {
1243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasTelephonyPermission = true;
1244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.WRITE_EXTERNAL_STORAGE") {
1245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasWriteExternalStoragePermission = true;
1246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.READ_EXTERNAL_STORAGE") {
1247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasReadExternalStoragePermission = true;
1248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.READ_PHONE_STATE") {
1249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasReadPhoneStatePermission = true;
1250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.READ_CONTACTS") {
1251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasReadContactsPermission = true;
1252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.WRITE_CONTACTS") {
1253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasWriteContactsPermission = true;
1254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.READ_CALL_LOG") {
1255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasReadCallLogPermission = true;
1256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.WRITE_CALL_LOG") {
1257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasWriteCallLogPermission = true;
1258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
125958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski
126058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                            printUsesPermission(name,
126158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                                    getIntegerAttribute(tree, REQUIRED_ATTR, NULL, 1) == 0,
126258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                                    getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR, NULL, -1));
126358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                       } else {
1264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    error.string());
1266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            goto bail;
1267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "uses-package") {
1269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8 name = getAttribute(tree, NAME_ATTR, &error);
1270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (name != "" && error == "") {
12712675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            printf("uses-package:'%s'\n",
12722675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                    ResTable::normalizeForOutput(name.string()).string());
1273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else {
1274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    error.string());
1276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                goto bail;
1277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "original-package") {
1279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8 name = getAttribute(tree, NAME_ATTR, &error);
1280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (name != "" && error == "") {
12812675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            printf("original-package:'%s'\n",
12822675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                    ResTable::normalizeForOutput(name.string()).string());
1283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else {
1284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    error.string());
1286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                goto bail;
1287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "supports-gl-texture") {
1289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8 name = getAttribute(tree, NAME_ATTR, &error);
1290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (name != "" && error == "") {
12912675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            printf("supports-gl-texture:'%s'\n",
12922675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                    ResTable::normalizeForOutput(name.string()).string());
1293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else {
1294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    error.string());
1296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                goto bail;
1297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "compatible-screens") {
1299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        printCompatibleScreens(tree);
1300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        depth--;
1301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "package-verifier") {
1302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8 name = getAttribute(tree, NAME_ATTR, &error);
1303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (name != "" && error == "") {
1304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            String8 publicKey = getAttribute(tree, PUBLIC_KEY_ATTR, &error);
1305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (publicKey != "" && error == "") {
1306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                printf("package-verifier: name='%s' publicKey='%s'\n",
13072675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                        ResTable::normalizeForOutput(name.string()).string(),
13082675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                        ResTable::normalizeForOutput(publicKey.string()).string());
1309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1312ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                } else if (depth == 3) {
1313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    withinActivity = false;
1314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    withinReceiver = false;
1315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    withinService = false;
1316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasIntentFilter = false;
131794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    hasMetaHostPaymentCategory = false;
131894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    hasMetaOffHostPaymentCategory = false;
131994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    hasBindDeviceAdminPermission = false;
132094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    hasBindInputMethodPermission = false;
132194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    hasBindAccessibilityServicePermission = false;
132294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    hasBindPrintServicePermission = false;
132394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    hasBindNfcServicePermission = false;
1324ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                    if (withinApplication) {
1325ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        if(tag == "activity") {
1326ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            withinActivity = true;
1327ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            activityName = getAttribute(tree, NAME_ATTR, &error);
1328ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (error != "") {
1329ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1330ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        error.string());
1331ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                goto bail;
1332ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
1333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1334ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            activityLabel = getResolvedAttribute(&res, tree, LABEL_ATTR, &error);
1335ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (error != "") {
1336ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                fprintf(stderr, "ERROR getting 'android:label' attribute: %s\n",
1337ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        error.string());
1338ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                goto bail;
1339ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
1340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1341ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            activityIcon = getResolvedAttribute(&res, tree, ICON_ATTR, &error);
1342ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (error != "") {
1343ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n",
1344ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        error.string());
1345ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                goto bail;
1346ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
1347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
13480a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                            activityBanner = getResolvedAttribute(&res, tree, BANNER_ATTR, &error);
13490a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                            if (error != "") {
13500a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                fprintf(stderr, "ERROR getting 'android:banner' attribute: %s\n",
13510a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                        error.string());
13520a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                goto bail;
13530a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                            }
13540a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn
1355ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            int32_t orien = getResolvedIntegerAttribute(&res, tree,
1356ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                    SCREEN_ORIENTATION_ATTR, &error);
1357ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (error == "") {
1358ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                if (orien == 0 || orien == 6 || orien == 8) {
1359ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                    // Requests landscape, sensorLandscape, or reverseLandscape.
1360ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                    reqScreenLandscapeFeature = true;
1361ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                } else if (orien == 1 || orien == 7 || orien == 9) {
1362ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                    // Requests portrait, sensorPortrait, or reversePortrait.
1363ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                    reqScreenPortraitFeature = true;
1364ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                }
1365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1366ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        } else if (tag == "uses-library") {
1367ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            String8 libraryName = getAttribute(tree, NAME_ATTR, &error);
1368ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (error != "") {
1369ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                fprintf(stderr,
1370ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        "ERROR getting 'android:name' attribute for uses-library"
1371ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        " %s\n", error.string());
1372ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                goto bail;
1373ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
1374ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            int req = getIntegerAttribute(tree,
1375ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                    REQUIRED_ATTR, NULL, 1);
1376ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            printf("uses-library%s:'%s'\n",
13772675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                    req ? "" : "-not-required", ResTable::normalizeForOutput(
13782675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                            libraryName.string()).string());
1379ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        } else if (tag == "receiver") {
1380ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            withinReceiver = true;
1381ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            receiverName = getAttribute(tree, NAME_ATTR, &error);
1382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1383ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (error != "") {
1384ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                fprintf(stderr,
1385ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        "ERROR getting 'android:name' attribute for receiver:"
1386ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        " %s\n", error.string());
1387ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                goto bail;
1388ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
1389a5018c900f126ee8424c82497f32983873db741bAdam Lesinski
1390a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            String8 permission = getAttribute(tree, PERMISSION_ATTR, &error);
1391a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            if (error == "") {
1392a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                if (permission == "android.permission.BIND_DEVICE_ADMIN") {
1393a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                    hasBindDeviceAdminPermission = true;
1394a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                }
1395a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            } else {
1396a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                fprintf(stderr, "ERROR getting 'android:permission' attribute for"
1397a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                        " receiver '%s': %s\n", receiverName.string(), error.string());
1398a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            }
1399ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        } else if (tag == "service") {
1400ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            withinService = true;
1401ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            serviceName = getAttribute(tree, NAME_ATTR, &error);
1402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1403ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (error != "") {
1404ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                fprintf(stderr, "ERROR getting 'android:name' attribute for "
1405ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        "service:%s\n", error.string());
1406ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                goto bail;
1407ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
1408a5018c900f126ee8424c82497f32983873db741bAdam Lesinski
1409a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            String8 permission = getAttribute(tree, PERMISSION_ATTR, &error);
1410a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            if (error == "") {
1411a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                if (permission == "android.permission.BIND_INPUT_METHOD") {
1412a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                    hasBindInputMethodPermission = true;
1413a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                } else if (permission == "android.permission.BIND_ACCESSIBILITY_SERVICE") {
1414a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                    hasBindAccessibilityServicePermission = true;
1415a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                } else if (permission == "android.permission.BIND_PRINT_SERVICE") {
1416a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                    hasBindPrintServicePermission = true;
141794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                } else if (permission == "android.permission.BIND_NFC_SERVICE") {
141894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                    hasBindNfcServicePermission = true;
1419a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                }
1420a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            } else {
1421a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                fprintf(stderr, "ERROR getting 'android:permission' attribute for"
1422a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                        " service '%s': %s\n", serviceName.string(), error.string());
1423a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            }
1424ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        } else if (bundle->getIncludeMetaData() && tag == "meta-data") {
1425ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            String8 metaDataName = getAttribute(tree, NAME_ATTR, &error);
1426ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (error != "") {
1427ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                fprintf(stderr, "ERROR getting 'android:name' attribute for "
1428ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        "meta-data:%s\n", error.string());
1429ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                goto bail;
1430ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
14312675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            printf("meta-data: name='%s' ",
14322675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                    ResTable::normalizeForOutput(metaDataName.string()).string());
143376327314d2238e105f8b94909f9c0cf85caca318Maurice Chu                            printResolvedResourceAttribute(&res, tree, VALUE_ATTR, String8("value"),
143476327314d2238e105f8b94909f9c0cf85caca318Maurice Chu                                    &error);
1435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (error != "") {
143676327314d2238e105f8b94909f9c0cf85caca318Maurice Chu                                // Try looking for a RESOURCE_ATTR
143776327314d2238e105f8b94909f9c0cf85caca318Maurice Chu                                error = "";
143876327314d2238e105f8b94909f9c0cf85caca318Maurice Chu                                printResolvedResourceAttribute(&res, tree, RESOURCE_ATTR,
143976327314d2238e105f8b94909f9c0cf85caca318Maurice Chu                                        String8("resource"), &error);
1440ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                if (error != "") {
144176327314d2238e105f8b94909f9c0cf85caca318Maurice Chu                                    fprintf(stderr, "ERROR getting 'android:value' or "
144276327314d2238e105f8b94909f9c0cf85caca318Maurice Chu                                            "'android:resource' attribute for "
144376327314d2238e105f8b94909f9c0cf85caca318Maurice Chu                                            "meta-data:%s\n", error.string());
1444ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                    goto bail;
1445ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                }
1446ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
144776327314d2238e105f8b94909f9c0cf85caca318Maurice Chu                            printf("\n");
1448ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        } else if (withinSupportsInput && tag == "input-type") {
1449ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            String8 name = getAttribute(tree, NAME_ATTR, &error);
1450ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (name != "" && error == "") {
1451ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                supportedInput.add(name);
1452ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            } else {
1453ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1454ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        error.string());
1455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                goto bail;
1456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1458a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                    }
145994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                } else if (depth == 4) {
146094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    if (tag == "intent-filter") {
146194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        hasIntentFilter = true;
146294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        withinIntentFilter = true;
146394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actMainActivity = false;
146494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actWidgetReceivers = false;
146594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actImeService = false;
146694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actWallpaperService = false;
146794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actAccessibilityService = false;
146894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actPrintService = false;
146994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actDeviceAdminEnabled = false;
147094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actHostApduService = false;
147194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actOffHostApduService = false;
147294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    } else if (withinService && tag == "meta-data") {
147394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        String8 name = getAttribute(tree, NAME_ATTR, &error);
147494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        if (error != "") {
147594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            fprintf(stderr, "ERROR getting 'android:name' attribute for"
147694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                    " meta-data tag in service '%s': %s\n", serviceName.string(), error.string());
147794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            goto bail;
147894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        }
147994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
148094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        if (name == "android.nfc.cardemulation.host_apdu_service" ||
148194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                name == "android.nfc.cardemulation.off_host_apdu_service") {
148294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            bool offHost = true;
148394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            if (name == "android.nfc.cardemulation.host_apdu_service") {
148494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                offHost = false;
148594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            }
148694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
148794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            String8 xmlPath = getResolvedAttribute(&res, tree, RESOURCE_ATTR, &error);
148894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            if (error != "") {
148994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                fprintf(stderr, "ERROR getting 'android:resource' attribute for"
149094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                        " meta-data tag in service '%s': %s\n", serviceName.string(), error.string());
149194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                goto bail;
149294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            }
149394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
149494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            Vector<String8> categories = getNfcAidCategories(assets, xmlPath,
149594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                    offHost, &error);
149694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            if (error != "") {
149794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                fprintf(stderr, "ERROR getting AID category for service '%s'\n",
149894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                        serviceName.string());
149994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                goto bail;
150094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            }
150194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
150294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            const size_t catLen = categories.size();
150394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            for (size_t i = 0; i < catLen; i++) {
150494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                bool paymentCategory = (categories[i] == "payment");
150594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                if (offHost) {
150694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                    hasMetaOffHostPaymentCategory |= paymentCategory;
150794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                } else {
150894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                    hasMetaHostPaymentCategory |= paymentCategory;
150994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                }
151094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            }
151194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        }
151294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    }
1513a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                } else if ((depth == 5) && withinIntentFilter) {
1514a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                    String8 action;
1515a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                    if (tag == "action") {
1516a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        action = getAttribute(tree, NAME_ATTR, &error);
1517a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        if (error != "") {
1518a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1519a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                    error.string());
1520a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            goto bail;
1521a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        }
1522a5018c900f126ee8424c82497f32983873db741bAdam Lesinski
1523a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        if (withinActivity) {
1524a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            if (action == "android.intent.action.MAIN") {
1525a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                isMainActivity = true;
1526a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                actMainActivity = true;
1527282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1528a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        } else if (withinReceiver) {
1529a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            if (action == "android.appwidget.action.APPWIDGET_UPDATE") {
1530a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                actWidgetReceivers = true;
1531a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            } else if (action == "android.app.action.DEVICE_ADMIN_ENABLED") {
1532a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                actDeviceAdminEnabled = true;
1533282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1534a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        } else if (withinService) {
1535a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            if (action == "android.view.InputMethod") {
1536a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                actImeService = true;
1537a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            } else if (action == "android.service.wallpaper.WallpaperService") {
1538a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                actWallpaperService = true;
1539a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            } else if (action == "android.accessibilityservice.AccessibilityService") {
1540a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                actAccessibilityService = true;
1541a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            } else if (action == "android.printservice.PrintService") {
1542a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                actPrintService = true;
154394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            } else if (action == "android.nfc.cardemulation.action.HOST_APDU_SERVICE") {
154494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                actHostApduService = true;
154594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            } else if (action == "android.nfc.cardemulation.action.OFF_HOST_APDU_SERVICE") {
154694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                actOffHostApduService = true;
1547282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1548282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1549a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        if (action == "android.intent.action.SEARCH") {
1550a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            isSearchable = true;
1551a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        }
1552a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                    }
1553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1554a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                    if (tag == "category") {
1555a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        String8 category = getAttribute(tree, NAME_ATTR, &error);
1556a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        if (error != "") {
1557a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            fprintf(stderr, "ERROR getting 'name' attribute: %s\n",
1558a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                    error.string());
1559a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            goto bail;
1560a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        }
1561a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        if (withinActivity) {
1562a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            if (category == "android.intent.category.LAUNCHER") {
1563a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                isLauncherActivity = true;
15640a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                            } else if (category == "android.intent.category.LEANBACK_LAUNCHER") {
15650a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                isLeanbackLauncherActivity = true;
1566282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1567282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1568282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1569282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1570282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1571282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Pre-1.6 implicitly granted permission compatibility logic
1573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (targetSdk < 4) {
1574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!hasWriteExternalStoragePermission) {
157558f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesPermission(String8("android.permission.WRITE_EXTERNAL_STORAGE"));
157658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesImpliedPermission(String8("android.permission.WRITE_EXTERNAL_STORAGE"),
157758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                            String8("targetSdkVersion < 4"));
1578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasWriteExternalStoragePermission = true;
1579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!hasReadPhoneStatePermission) {
158158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesPermission(String8("android.permission.READ_PHONE_STATE"));
158258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesImpliedPermission(String8("android.permission.READ_PHONE_STATE"),
158358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                            String8("targetSdkVersion < 4"));
1584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // If the application has requested WRITE_EXTERNAL_STORAGE, we will
1588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // force them to always take READ_EXTERNAL_STORAGE as well.  We always
1589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // do this (regardless of target API version) because we can't have
1590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // an app with write permission but not read permission.
1591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!hasReadExternalStoragePermission && hasWriteExternalStoragePermission) {
159258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                printUsesPermission(String8("android.permission.READ_EXTERNAL_STORAGE"));
159358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                printUsesImpliedPermission(String8("android.permission.READ_EXTERNAL_STORAGE"),
159458f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                        String8("requested WRITE_EXTERNAL_STORAGE"));
1595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Pre-JellyBean call log permission compatibility.
1598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (targetSdk < 16) {
1599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!hasReadCallLogPermission && hasReadContactsPermission) {
160058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesPermission(String8("android.permission.READ_CALL_LOG"));
160158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesImpliedPermission(String8("android.permission.READ_CALL_LOG"),
160258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                            String8("targetSdkVersion < 16 and requested READ_CONTACTS"));
1603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!hasWriteCallLogPermission && hasWriteContactsPermission) {
160558f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesPermission(String8("android.permission.WRITE_CALL_LOG"));
160658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesImpliedPermission(String8("android.permission.WRITE_CALL_LOG"),
160758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                            String8("targetSdkVersion < 16 and requested WRITE_CONTACTS"));
1608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            /* The following blocks handle printing "inferred" uses-features, based
1612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             * on whether related features or permissions are used by the app.
1613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             * Note that the various spec*Feature variables denote whether the
1614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             * relevant tag was *present* in the AndroidManfest, not that it was
1615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             * present and set to true.
1616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             */
1617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Camera-related back-compatibility logic
1618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!specCameraFeature) {
1619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (reqCameraFlashFeature) {
1620282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // if app requested a sub-feature (autofocus or flash) and didn't
1621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // request the base camera feature, we infer that it meant to
1622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    printf("uses-feature:'android.hardware.camera'\n");
1623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    printf("uses-implied-feature:'android.hardware.camera'," \
1624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            "'requested android.hardware.camera.flash feature'\n");
1625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else if (reqCameraAutofocusFeature) {
1626282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // if app requested a sub-feature (autofocus or flash) and didn't
1627282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // request the base camera feature, we infer that it meant to
1628282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    printf("uses-feature:'android.hardware.camera'\n");
1629282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    printf("uses-implied-feature:'android.hardware.camera'," \
1630282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            "'requested android.hardware.camera.autofocus feature'\n");
1631282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else if (hasCameraPermission) {
16322675f769673f69b0661ddee346292f25cb30a296Maurice Chu                    // if app wants to use camera but didn't request the feature, we infer
1633282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // that it meant to, and further that it wants autofocus
1634282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // (which was the 1.0 - 1.5 behavior)
1635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    printf("uses-feature:'android.hardware.camera'\n");
1636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (!specCameraAutofocusFeature) {
1637282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        printf("uses-feature:'android.hardware.camera.autofocus'\n");
1638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        printf("uses-implied-feature:'android.hardware.camera.autofocus'," \
1639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                "'requested android.permission.CAMERA permission'\n");
1640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1644282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Location-related back-compatibility logic
1645282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!specLocationFeature &&
1646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                (hasMockLocPermission || hasCoarseLocPermission || hasGpsPermission ||
1647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 hasGeneralLocPermission || reqNetworkLocFeature || reqGpsFeature)) {
1648282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // if app either takes a location-related permission or requests one of the
1649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // sub-features, we infer that it also meant to request the base location feature
1650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("uses-feature:'android.hardware.location'\n");
1651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("uses-implied-feature:'android.hardware.location'," \
1652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "'requested a location access permission'\n");
1653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!specGpsFeature && hasGpsPermission) {
1655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // if app takes GPS (FINE location) perm but does not request the GPS
1656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // feature, we infer that it meant to
1657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("uses-feature:'android.hardware.location.gps'\n");
1658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("uses-implied-feature:'android.hardware.location.gps'," \
1659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "'requested android.permission.ACCESS_FINE_LOCATION permission'\n");
1660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!specNetworkLocFeature && hasCoarseLocPermission) {
1662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // if app takes Network location (COARSE location) perm but does not request the
1663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // network location feature, we infer that it meant to
1664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("uses-feature:'android.hardware.location.network'\n");
1665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("uses-implied-feature:'android.hardware.location.network'," \
1666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "'requested android.permission.ACCESS_COARSE_LOCATION permission'\n");
1667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Bluetooth-related compatibility logic
1670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!specBluetoothFeature && hasBluetoothPermission && (targetSdk > 4)) {
1671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // if app takes a Bluetooth permission but does not request the Bluetooth
1672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // feature, we infer that it meant to
1673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("uses-feature:'android.hardware.bluetooth'\n");
1674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("uses-implied-feature:'android.hardware.bluetooth'," \
1675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "'requested android.permission.BLUETOOTH or android.permission.BLUETOOTH_ADMIN " \
1676282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "permission and targetSdkVersion > 4'\n");
1677282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1679282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Microphone-related compatibility logic
1680282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!specMicrophoneFeature && hasRecordAudioPermission) {
1681282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // if app takes the record-audio permission but does not request the microphone
1682282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // feature, we infer that it meant to
1683282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("uses-feature:'android.hardware.microphone'\n");
1684282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("uses-implied-feature:'android.hardware.microphone'," \
1685282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "'requested android.permission.RECORD_AUDIO permission'\n");
1686282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1687282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // WiFi-related compatibility logic
1689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!specWiFiFeature && hasWiFiPermission) {
1690282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // if app takes one of the WiFi permissions but does not request the WiFi
1691282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // feature, we infer that it meant to
1692282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("uses-feature:'android.hardware.wifi'\n");
1693282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("uses-implied-feature:'android.hardware.wifi'," \
1694282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "'requested android.permission.ACCESS_WIFI_STATE, " \
1695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "android.permission.CHANGE_WIFI_STATE, or " \
1696282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "android.permission.CHANGE_WIFI_MULTICAST_STATE permission'\n");
1697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Telephony-related compatibility logic
1700282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!specTelephonyFeature && (hasTelephonyPermission || reqTelephonySubFeature)) {
1701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // if app takes one of the telephony permissions or requests a sub-feature but
1702282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // does not request the base telephony feature, we infer that it meant to
1703282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("uses-feature:'android.hardware.telephony'\n");
1704282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("uses-implied-feature:'android.hardware.telephony'," \
1705282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "'requested a telephony-related permission or feature'\n");
1706282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1707282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1708282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Touchscreen-related back-compatibility logic
1709282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!specTouchscreenFeature) { // not a typo!
1710282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // all apps are presumed to require a touchscreen, unless they explicitly say
1711282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // <uses-feature android:name="android.hardware.touchscreen" android:required="false"/>
1712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Note that specTouchscreenFeature is true if the tag is present, regardless
1713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // of whether its value is true or false, so this is safe
1714282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("uses-feature:'android.hardware.touchscreen'\n");
1715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("uses-implied-feature:'android.hardware.touchscreen'," \
1716282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "'assumed you require a touch screen unless explicitly made optional'\n");
1717282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1718282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!specMultitouchFeature && reqDistinctMultitouchFeature) {
1719282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // if app takes one of the telephony permissions or requests a sub-feature but
1720282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // does not request the base telephony feature, we infer that it meant to
1721282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("uses-feature:'android.hardware.touchscreen.multitouch'\n");
1722282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("uses-implied-feature:'android.hardware.touchscreen.multitouch'," \
1723282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "'requested android.hardware.touchscreen.multitouch.distinct feature'\n");
1724282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1725282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1726282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Landscape/portrait-related compatibility logic
1727282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!specScreenLandscapeFeature && !specScreenPortraitFeature) {
1728282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // If the app has specified any activities in its manifest
1729282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // that request a specific orientation, then assume that
1730282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // orientation is required.
1731282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (reqScreenLandscapeFeature) {
1732282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    printf("uses-feature:'android.hardware.screen.landscape'\n");
1733282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    printf("uses-implied-feature:'android.hardware.screen.landscape'," \
1734282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            "'one or more activities have specified a landscape orientation'\n");
1735282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1736282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (reqScreenPortraitFeature) {
1737282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    printf("uses-feature:'android.hardware.screen.portrait'\n");
1738282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    printf("uses-implied-feature:'android.hardware.screen.portrait'," \
1739282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            "'one or more activities have specified a portrait orientation'\n");
1740282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1741282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1742282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1743282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (hasMainActivity) {
1744282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("main\n");
1745282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1746282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (hasWidgetReceivers) {
1747282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("app-widget\n");
1748282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1749a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            if (hasDeviceAdminReceiver) {
1750a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                printf("device-admin\n");
1751a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            }
1752282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (hasImeService) {
1753282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("ime\n");
1754282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1755282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (hasWallpaperService) {
1756282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("wallpaper\n");
1757282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1758a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            if (hasAccessibilityService) {
1759a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                printf("accessibility\n");
1760a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            }
1761a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            if (hasPrintService) {
1762a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                printf("print\n");
1763a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            }
176494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            if (hasPaymentService) {
176594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                printf("payment\n");
176694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            }
1767282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (hasOtherActivities) {
1768282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("other-activities\n");
1769282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1770282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (isSearchable) {
1771282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("search\n");
1772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (hasOtherReceivers) {
1774282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("other-receivers\n");
1775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1776282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (hasOtherServices) {
1777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("other-services\n");
1778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // For modern apps, if screen size buckets haven't been specified
1781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // but the new width ranges have, then infer the buckets from them.
1782282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (smallScreen > 0 && normalScreen > 0 && largeScreen > 0 && xlargeScreen > 0
1783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    && requiresSmallestWidthDp > 0) {
1784282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                int compatWidth = compatibleWidthLimitDp;
1785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (compatWidth <= 0) {
1786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    compatWidth = requiresSmallestWidthDp;
1787282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1788282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (requiresSmallestWidthDp <= 240 && compatWidth >= 240) {
1789282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    smallScreen = -1;
1790282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1791282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    smallScreen = 0;
1792282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1793282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (requiresSmallestWidthDp <= 320 && compatWidth >= 320) {
1794282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    normalScreen = -1;
1795282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1796282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    normalScreen = 0;
1797282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1798282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (requiresSmallestWidthDp <= 480 && compatWidth >= 480) {
1799282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    largeScreen = -1;
1800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1801282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    largeScreen = 0;
1802282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1803282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (requiresSmallestWidthDp <= 720 && compatWidth >= 720) {
1804282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    xlargeScreen = -1;
1805282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1806282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    xlargeScreen = 0;
1807282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1808282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1809282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1810282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Determine default values for any unspecified screen sizes,
1811282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // based on the target SDK of the package.  As of 4 (donut)
1812282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // the screen size support was introduced, so all default to
1813282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // enabled.
1814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (smallScreen > 0) {
1815282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                smallScreen = targetSdk >= 4 ? -1 : 0;
1816282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1817282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (normalScreen > 0) {
1818282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                normalScreen = -1;
1819282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1820282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (largeScreen > 0) {
1821282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                largeScreen = targetSdk >= 4 ? -1 : 0;
1822282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1823282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (xlargeScreen > 0) {
1824282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Introduced in Gingerbread.
1825282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                xlargeScreen = targetSdk >= 9 ? -1 : 0;
1826282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1827282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (anyDensity > 0) {
1828282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                anyDensity = (targetSdk >= 4 || requiresSmallestWidthDp > 0
1829282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        || compatibleWidthLimitDp > 0) ? -1 : 0;
1830282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1831282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("supports-screens:");
1832282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (smallScreen != 0) {
1833282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf(" 'small'");
1834282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1835282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (normalScreen != 0) {
1836282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf(" 'normal'");
1837282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1838282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (largeScreen != 0) {
1839282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf(" 'large'");
1840282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1841282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (xlargeScreen != 0) {
1842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf(" 'xlarge'");
1843282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1844282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("\n");
1845282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("supports-any-density: '%s'\n", anyDensity ? "true" : "false");
1846282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (requiresSmallestWidthDp > 0) {
1847282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("requires-smallest-width:'%d'\n", requiresSmallestWidthDp);
1848282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1849282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (compatibleWidthLimitDp > 0) {
1850282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("compatible-width-limit:'%d'\n", compatibleWidthLimitDp);
1851282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (largestWidthLimitDp > 0) {
1853282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("largest-width-limit:'%d'\n", largestWidthLimitDp);
1854282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1855282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1856282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("locales:");
1857282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t NL = locales.size();
1858282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t i=0; i<NL; i++) {
1859282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                const char* localeStr =  locales[i].string();
1860282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (localeStr == NULL || strlen(localeStr) == 0) {
1861282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    localeStr = "--_--";
1862282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1863282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf(" '%s'", localeStr);
1864282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1865282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("\n");
1866282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1867282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("densities:");
1868282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t ND = densities.size();
1869282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t i=0; i<ND; i++) {
1870282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf(" '%d'", densities[i]);
1871282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1872282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("\n");
1873282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1874282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            AssetDir* dir = assets.openNonAssetDir(assetsCookie, "lib");
1875282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (dir != NULL) {
1876282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (dir->getFileCount() > 0) {
1877282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    printf("native-code:");
1878282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    for (size_t i=0; i<dir->getFileCount(); i++) {
18792675f769673f69b0661ddee346292f25cb30a296Maurice Chu                        printf(" '%s'", ResTable::normalizeForOutput(
18802675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                dir->getFileName(i).string()).string());
1881282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1882282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    printf("\n");
1883282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1884282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                delete dir;
1885282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1886282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else if (strcmp("badger", option) == 0) {
1887282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("%s", CONSOLE_DATA);
1888282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else if (strcmp("configurations", option) == 0) {
1889282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Vector<ResTable_config> configs;
1890282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            res.getConfigurations(&configs);
1891282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t N = configs.size();
1892282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t i=0; i<N; i++) {
1893282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("%s\n", configs[i].toString().string());
1894282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1895282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
1896282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: unknown dump option '%s'\n", option);
1897282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
1898282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1899282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1900282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1901282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    result = NO_ERROR;
1902282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1903282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail:
1904282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (asset) {
1905282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        delete asset;
1906282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1907282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return (result != NO_ERROR);
1908282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1909282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1910282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1911282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
1912282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Handle the "add" command, which wants to add files to a new or
1913282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * pre-existing archive.
1914282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
1915282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doAdd(Bundle* bundle)
1916282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1917282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ZipFile* zip = NULL;
1918282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t result = UNKNOWN_ERROR;
1919282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char* zipFileName;
1920282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1921282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getUpdate()) {
1922282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        /* avoid confusion */
1923282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: can't use '-u' with add\n");
1924282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
1925282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1926282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1927282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getFileSpecCount() < 1) {
1928282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: must specify zip file name\n");
1929282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
1930282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1931282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    zipFileName = bundle->getFileSpecEntry(0);
1932282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1933282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getFileSpecCount() < 2) {
1934282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "NOTE: nothing to do\n");
1935282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
1936282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1937282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1938282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    zip = openReadWrite(zipFileName, true);
1939282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (zip == NULL) {
1940282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: failed opening/creating '%s' as Zip file\n", zipFileName);
1941282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
1942282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1943282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1944282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (int i = 1; i < bundle->getFileSpecCount(); i++) {
1945282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const char* fileName = bundle->getFileSpecEntry(i);
1946282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1947282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (strcasecmp(String8(fileName).getPathExtension().string(), ".gz") == 0) {
1948282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf(" '%s'... (from gzip)\n", fileName);
1949282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            result = zip->addGzip(fileName, String8(fileName).getBasePath().string(), NULL);
1950282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
1951282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (bundle->getJunkPath()) {
1952282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String8 storageName = String8(fileName).getPathLeaf();
19532675f769673f69b0661ddee346292f25cb30a296Maurice Chu                printf(" '%s' as '%s'...\n", fileName,
19542675f769673f69b0661ddee346292f25cb30a296Maurice Chu                        ResTable::normalizeForOutput(storageName.string()).string());
1955282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                result = zip->add(fileName, storageName.string(),
1956282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  bundle->getCompressionMethod(), NULL);
1957282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
1958282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf(" '%s'...\n", fileName);
1959282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                result = zip->add(fileName, bundle->getCompressionMethod(), NULL);
1960282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1961282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1962282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (result != NO_ERROR) {
1963282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "Unable to add '%s' to '%s'", bundle->getFileSpecEntry(i), zipFileName);
1964282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (result == NAME_NOT_FOUND) {
1965282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, ": file not found\n");
1966282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (result == ALREADY_EXISTS) {
1967282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, ": already exists in archive\n");
1968282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
1969282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, "\n");
1970282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1971282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
1972282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1973282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1974282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1975282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    result = NO_ERROR;
1976282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1977282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail:
1978282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    delete zip;
1979282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return (result != NO_ERROR);
1980282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1981282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1982282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1983282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
1984282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Delete files from an existing archive.
1985282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
1986282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doRemove(Bundle* bundle)
1987282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1988282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ZipFile* zip = NULL;
1989282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t result = UNKNOWN_ERROR;
1990282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char* zipFileName;
1991282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1992282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getFileSpecCount() < 1) {
1993282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: must specify zip file name\n");
1994282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
1995282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1996282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    zipFileName = bundle->getFileSpecEntry(0);
1997282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1998282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getFileSpecCount() < 2) {
1999282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "NOTE: nothing to do\n");
2000282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2001282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2002282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2003282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    zip = openReadWrite(zipFileName, false);
2004282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (zip == NULL) {
2005282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: failed opening Zip archive '%s'\n",
2006282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            zipFileName);
2007282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2008282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2009282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2010282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (int i = 1; i < bundle->getFileSpecCount(); i++) {
2011282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const char* fileName = bundle->getFileSpecEntry(i);
2012282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ZipEntry* entry;
2013282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2014282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        entry = zip->getEntryByName(fileName);
2015282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (entry == NULL) {
2016282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf(" '%s' NOT FOUND\n", fileName);
2017282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
2018282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2019282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2020282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        result = zip->remove(entry);
2021282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2022282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (result != NO_ERROR) {
2023282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "Unable to delete '%s' from '%s'\n",
2024282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                bundle->getFileSpecEntry(i), zipFileName);
2025282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
2026282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2027282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2028282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2029282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /* update the archive */
2030282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    zip->flush();
2031282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2032282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail:
2033282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    delete zip;
2034282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return (result != NO_ERROR);
2035282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2036282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2037282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2038282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
2039282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Package up an asset directory and associated application files.
2040282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
2041282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doPackage(Bundle* bundle)
2042282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2043282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char* outputAPKFile;
2044282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int retVal = 1;
2045282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err;
2046282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<AaptAssets> assets;
2047282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int N;
2048282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    FILE* fp;
2049282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String8 dependencyFile;
2050282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2051282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // -c zz_ZZ means do pseudolocalization
2052282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ResourceFilter filter;
2053282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    err = filter.parse(bundle->getConfigurations());
2054282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
2055282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2056282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2057282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (filter.containsPseudo()) {
2058282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        bundle->setPseudolocalize(true);
2059282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2060282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2061282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    N = bundle->getFileSpecCount();
2062282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (N < 1 && bundle->getResourceSourceDirs().size() == 0 && bundle->getJarFiles().size() == 0
206309384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski            && bundle->getAndroidManifestFile() == NULL && bundle->getAssetSourceDirs().size() == 0) {
2064282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: no input files\n");
2065282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2066282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2067282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2068282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    outputAPKFile = bundle->getOutputAPKFile();
2069282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2070282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Make sure the filenames provided exist and are of the appropriate type.
2071282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (outputAPKFile) {
2072282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        FileType type;
2073282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        type = getFileType(outputAPKFile);
2074282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (type != kFileTypeNonexistent && type != kFileTypeRegular) {
2075282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr,
2076282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                "ERROR: output file '%s' exists but is not regular file\n",
2077282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                outputAPKFile);
2078282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
2079282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2080282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2081282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2082282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Load the assets.
2083282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    assets = new AaptAssets();
2084282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2085282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Set up the resource gathering in assets if we're going to generate
2086282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // dependency files. Every time we encounter a resource while slurping
2087282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // the tree, we'll add it to these stores so we have full resource paths
2088282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // to write to a dependency file.
2089282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getGenDependencies()) {
2090282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<FilePathStore> resPathStore = new FilePathStore;
2091282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        assets->setFullResPaths(resPathStore);
2092282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<FilePathStore> assetPathStore = new FilePathStore;
2093282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        assets->setFullAssetPaths(assetPathStore);
2094282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2095282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2096282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    err = assets->slurpFromArgs(bundle);
2097282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err < 0) {
2098282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2099282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getVerbose()) {
2102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        assets->print(String8());
2103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // If they asked for any fileAs that need to be compiled, do so.
2106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getResourceSourceDirs().size() || bundle->getAndroidManifestFile()) {
2107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        err = buildResources(bundle, assets);
2108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != 0) {
2109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
2110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // At this point we've read everything and processed everything.  From here
2114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // on out it's just writing output files.
2115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (SourcePos::hasErrors()) {
2116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Update symbols with information about which ones are needed as Java symbols.
2120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    assets->applyJavaSymbols();
2121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (SourcePos::hasErrors()) {
2122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // If we've been asked to generate a dependency file, do that here
2126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getGenDependencies()) {
2127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // If this is the packaging step, generate the dependency file next to
2128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // the output apk (e.g. bin/resources.ap_.d)
2129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (outputAPKFile) {
2130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            dependencyFile = String8(outputAPKFile);
2131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Add the .d extension to the dependency file.
2132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            dependencyFile.append(".d");
2133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
2134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Else if this is the R.java dependency generation step,
2135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // generate the dependency file in the R.java package subdirectory
2136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // e.g. gen/com/foo/app/R.java.d
2137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            dependencyFile = String8(bundle->getRClassDir());
2138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            dependencyFile.appendPath("R.java.d");
2139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Make sure we have a clean dependency file to start with
2141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fp = fopen(dependencyFile, "w");
2142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fclose(fp);
2143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Write out R.java constants
2146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (!assets->havePrivateSymbols()) {
2147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (bundle->getCustomPackage() == NULL) {
2148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Write the R.java file into the appropriate class directory
2149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // e.g. gen/com/foo/app/R.java
2150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            err = writeResourceSymbols(bundle, assets, assets->getPackage(), true);
2151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
2152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const String8 customPkg(bundle->getCustomPackage());
2153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            err = writeResourceSymbols(bundle, assets, customPkg, true);
2154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err < 0) {
2156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
2157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // If we have library files, we're going to write our R.java file into
2159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // the appropriate class directory for those libraries as well.
2160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // e.g. gen/com/foo/app/lib/R.java
2161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (bundle->getExtraPackages() != NULL) {
2162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Split on colon
2163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 libs(bundle->getExtraPackages());
2164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            char* packageString = strtok(libs.lockBuffer(libs.length()), ":");
2165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            while (packageString != NULL) {
2166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Write the R.java file out with the correct package name
2167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                err = writeResourceSymbols(bundle, assets, String8(packageString), true);
2168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (err < 0) {
2169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    goto bail;
2170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                packageString = strtok(NULL, ":");
2172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            libs.unlockBuffer();
2174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
2176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        err = writeResourceSymbols(bundle, assets, assets->getPackage(), false);
2177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err < 0) {
2178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
2179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        err = writeResourceSymbols(bundle, assets, assets->getSymbolsPrivatePackage(), true);
2181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err < 0) {
2182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
2183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Write out the ProGuard file
2187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    err = writeProguardFile(bundle, assets);
2188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err < 0) {
2189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Write the apk
2193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (outputAPKFile) {
2194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        err = writeAPK(bundle, assets, String8(outputAPKFile));
2195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != NO_ERROR) {
2196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: packaging of '%s' failed\n", outputAPKFile);
2197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
2198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // If we've been asked to generate a dependency file, we need to finish up here.
2202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // the writeResourceSymbols and writeAPK functions have already written the target
2203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // half of the dependency file, now we need to write the prerequisites. (files that
2204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // the R.java file or .ap_ file depend on)
2205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getGenDependencies()) {
2206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Now that writeResourceSymbols or writeAPK has taken care of writing
2207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // the targets to our dependency file, we'll write the prereqs
2208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fp = fopen(dependencyFile, "a+");
2209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(fp, " : ");
2210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        bool includeRaw = (outputAPKFile != NULL);
2211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        err = writeDependencyPreReqs(bundle, assets, fp, includeRaw);
2212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Also manually add the AndroidManifeset since it's not under res/ or assets/
2213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // and therefore was not added to our pathstores during slurping
2214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(fp, "%s \\\n", bundle->getAndroidManifestFile());
2215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fclose(fp);
2216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    retVal = 0;
2219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail:
2220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (SourcePos::hasErrors()) {
2221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        SourcePos::printErrors(stderr);
2222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return retVal;
2224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
2227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Do PNG Crunching
2228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * PRECONDITIONS
2229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *  -S flag points to a source directory containing drawable* folders
2230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *  -C flag points to destination directory. The folder structure in the
2231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *     source directory will be mirrored to the destination (cache) directory
2232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
2233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * POSTCONDITIONS
2234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *  Destination directory will be updated to match the PNG files in
22352675f769673f69b0661ddee346292f25cb30a296Maurice Chu *  the source directory.
2236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
2237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doCrunch(Bundle* bundle)
2238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(stdout, "Crunching PNG Files in ");
2240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(stdout, "source dir: %s\n", bundle->getResourceSourceDirs()[0]);
2241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(stdout, "To destination dir: %s\n", bundle->getCrunchedOutputDir());
2242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    updatePreProcessedCache(bundle);
2244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
2246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
2249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Do PNG Crunching on a single flag
2250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *  -i points to a single png file
2251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *  -o points to a single png output file
2252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
2253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doSingleCrunch(Bundle* bundle)
2254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(stdout, "Crunching single PNG file: %s\n", bundle->getSingleCrunchInputFile());
2256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(stdout, "\tOutput file: %s\n", bundle->getSingleCrunchOutputFile());
2257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String8 input(bundle->getSingleCrunchInputFile());
2259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String8 output(bundle->getSingleCrunchOutputFile());
2260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (preProcessImageToCache(bundle, input, output) != NO_ERROR) {
2262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // we can't return the status_t as it gets truncate to the lower 8 bits.
2263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return 42;
2264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
2267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskichar CONSOLE_DATA[2925] = {
2270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 95, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32,
2274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 63,
2275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    86, 35, 40, 46, 46, 95, 95, 95, 95, 97, 97, 44, 32, 46, 124, 42, 33, 83,
2276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    62, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 46, 58, 59, 61, 59, 61, 81,
2279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 66, 96, 61, 61, 58, 46, 46, 46, 58, 32, 32, 32, 32, 32, 32,
2280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32,
2281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 46, 61, 59, 59, 59, 58, 106, 81, 81, 81, 81, 102, 59, 61, 59,
2283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 61, 61, 61, 58, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59,
2286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 58, 109, 81, 81, 81, 81, 61, 59, 59, 59, 59, 59, 58, 59, 59, 46, 32,
2287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 60, 81, 81, 81, 81, 87,
2290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    58, 59, 59, 59, 59, 59, 59, 61, 119, 44, 32, 32, 32, 32, 32, 32, 32, 32,
2291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32,
2292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46,
2293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    47, 61, 59, 59, 58, 100, 81, 81, 81, 81, 35, 58, 59, 59, 59, 59, 59, 58,
2294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    121, 81, 91, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 109, 58, 59, 59, 61, 81, 81,
2297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 109, 58, 59, 59, 59, 59, 61, 109, 81, 81, 76, 46, 32, 32, 32,
2298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32,
2299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 41, 87, 59, 61, 59, 41, 81, 81, 81, 81, 81, 81, 59, 61, 59,
2301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 58, 109, 81, 81, 87, 39, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 60, 81, 91, 59,
2304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 61, 81, 81, 81, 81, 81, 87, 43, 59, 58, 59, 60, 81, 81, 81, 76, 32,
2305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 52, 91, 58, 45, 59, 87, 81, 81, 81, 81,
2308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    70, 58, 58, 58, 59, 106, 81, 81, 81, 91, 32, 32, 32, 32, 32, 32, 32, 32,
2309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32,
2310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 93, 40, 32, 46, 59, 100, 81, 81, 81, 81, 40, 58, 46, 46, 58, 100, 81,
2312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 68, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 46, 46, 46, 32, 46, 46, 46, 32, 46, 32, 46, 45, 91, 59, 61, 58, 109,
2315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 87, 46, 58, 61, 59, 60, 81, 81, 80, 32, 32, 32, 32, 32, 32,
2316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32,
2317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 46, 46, 61, 59, 61, 61, 61, 59, 61, 61, 59,
2318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 58, 58, 46, 46, 41, 58, 59, 58, 81, 81, 81, 81, 69, 58, 59, 59,
2319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    60, 81, 81, 68, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 58, 59,
2321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    61, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 61, 46,
2322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    61, 59, 93, 81, 81, 81, 81, 107, 58, 59, 58, 109, 87, 68, 96, 32, 32, 32,
2323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 10, 32, 32, 32, 46, 60, 61, 61, 59, 59, 59, 59, 59, 59, 59, 59,
2325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 59, 59, 59, 59, 58, 58, 58, 115, 109, 68, 41, 36, 81,
2326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    109, 46, 61, 61, 81, 69, 96, 46, 58, 58, 46, 58, 46, 46, 32, 32, 32, 32,
2327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 46, 32, 95, 81,
2328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    67, 61, 61, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
2329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 58, 68, 39, 61, 105, 61, 63, 81, 119, 58, 106, 80, 32, 58,
2330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    61, 59, 59, 61, 59, 61, 59, 61, 46, 95, 32, 32, 32, 32, 32, 32, 32, 32,
2331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 10, 32, 32, 36, 81, 109, 105, 59, 61, 59, 59, 59,
2332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 46, 58, 37,
2333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    73, 108, 108, 62, 52, 81, 109, 34, 32, 61, 59, 59, 59, 59, 59, 59, 59, 59,
2334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 61, 59, 61, 61, 46, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10,
2335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 46, 45, 57, 101, 43, 43, 61, 61, 59, 59, 59, 59, 59, 59, 61, 59, 59,
2336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 59, 59, 58, 97, 46, 61, 108, 62, 126, 58, 106, 80, 96,
2337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    46, 61, 61, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 61,
2338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    97, 103, 97, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 45, 46, 32,
2339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    46, 32, 32, 32, 32, 32, 32, 32, 32, 45, 45, 45, 58, 59, 59, 59, 59, 61,
2340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    119, 81, 97, 124, 105, 124, 124, 39, 126, 95, 119, 58, 61, 58, 59, 59, 59,
2341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 119, 81, 81, 99, 32, 32,
2342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 58, 59, 59, 58, 106, 81, 81, 81, 109, 119,
2344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    119, 119, 109, 109, 81, 81, 122, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59,
2345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 58, 115, 81, 87, 81, 102, 32, 32, 32, 32, 32, 32, 10,
2346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 61, 58, 59, 61, 81, 81, 81, 81, 81, 81, 87, 87, 81, 81, 81, 81,
2348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 58, 59, 59, 59, 59, 59, 59, 59, 59, 58, 45, 45, 45, 59, 59, 59, 41,
2349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    87, 66, 33, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32,
2350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 59, 59, 93, 81,
2351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 40, 58, 59, 59, 59, 58,
2352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    45, 32, 46, 32, 32, 32, 32, 32, 46, 32, 126, 96, 32, 32, 32, 32, 32, 32,
2353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 58, 61, 59, 58, 81, 81, 81, 81, 81, 81, 81, 81,
2355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 81, 81, 40, 58, 59, 59, 59, 58, 32, 32, 32, 32, 32, 32, 32,
2356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32,
2357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58,
2358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 58, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 40, 58,
2359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 46, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 59, 60, 81, 81, 81, 81,
2362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 81, 81, 81, 81, 81, 81, 59, 61, 59, 59, 61, 32, 32, 32, 32,
2363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 58, 59, 59, 93, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
2366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 40, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32,
2368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 58, 106,
2369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 76, 58, 59, 59, 59,
2370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 61, 58, 58, 81, 81, 81, 81, 81, 81, 81, 81,
2373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 81, 81, 87, 58, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32,
2374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32,
2375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    58, 59, 61, 41, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 87, 59,
2377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    61, 58, 59, 59, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 58, 61, 81, 81, 81,
2380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 81, 81, 81, 81, 81, 81, 107, 58, 59, 59, 59, 59, 58, 32, 32,
2381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 58, 59, 59, 58, 51, 81, 81, 81, 81, 81, 81, 81, 81, 81,
2384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 102, 94, 59, 59, 59, 59, 59, 61, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32,
2386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 59,
2387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 43, 63, 36, 81, 81, 81, 87, 64, 86, 102, 58, 59, 59, 59, 59, 59,
2388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 59, 59, 59, 59, 43, 33,
2391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    58, 126, 126, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 32, 46, 32, 32,
2392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32,
2393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46,
2394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    61, 59, 59, 59, 58, 45, 58, 61, 59, 58, 58, 58, 61, 59, 59, 59, 59, 59,
2395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 59, 59, 58, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32,
2396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32,
2397282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 59, 59, 58, 95,
2398282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 45, 61, 59, 61, 59, 59, 59, 59, 59, 59, 59, 45, 58, 59, 59, 59, 59,
2399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    61, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 58, 61, 59, 59, 59, 59, 59, 61, 59, 61, 46, 46, 32, 45, 45, 45,
2402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 58, 45, 45, 46, 58, 59, 59, 59, 59, 59, 59, 61, 46, 32, 32, 32, 32,
2403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32,
2404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 58, 59, 59, 59, 59,
2405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 61, 59, 46, 32, 32, 46, 32, 46, 32, 58, 61, 59, 59,
2406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 59, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 45, 59, 59, 59, 59, 59, 59, 59, 59, 58, 32,
2409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59, 59, 58, 32,
2410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10,
2411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    46, 61, 59, 59, 59, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 61,
2413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    46, 61, 59, 59, 59, 59, 59, 59, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32,
2415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59,
2416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 32, 46, 61, 58, 59, 59, 59, 59,
2417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 58, 59, 59, 59, 59, 59, 59, 59, 59, 46, 46, 32, 32, 32,
2420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59, 59, 45, 32, 32, 32, 32, 32,
2421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32,
2422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 32, 45, 61,
2423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 58, 32, 46, 32, 32, 32, 32, 32, 32, 32, 58, 59, 59,
2424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 58, 45, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2426282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 45, 45, 45, 45, 32, 46, 32,
2427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 45, 61, 59, 58, 45, 45, 32, 32, 32,
2428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 46, 32, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10
2433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski  };
2434