1282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//
2282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// Copyright 2006 The Android Open Source Project
3282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//
4282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// Android Asset Packaging Tool main entry point.
5282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//
6ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski#include "AaptXml.h"
7fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski#include "ApkBuilder.h"
8282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "Bundle.h"
92c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include "Images.h"
102c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include "Main.h"
11282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "ResourceFilter.h"
12282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "ResourceTable.h"
13282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "XMLNode.h"
14282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
152c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include <utils/Errors.h>
162c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include <utils/KeyedVector.h>
172c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include <utils/List.h>
18282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <utils/Log.h>
192c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include <utils/SortedVector.h>
20282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <utils/threads.h>
212c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include <utils/Vector.h>
22282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
23282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <errno.h>
242c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include <fcntl.h>
25282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
266f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez#include <iostream>
276f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez#include <string>
286f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez#include <sstream>
296f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez
30282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiusing namespace android;
31282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
32ad751224401564dcc8338df3d5c4c5de7722be8fAdam Lesinski#ifndef AAPT_VERSION
33ad751224401564dcc8338df3d5c4c5de7722be8fAdam Lesinski    #define AAPT_VERSION ""
34ad751224401564dcc8338df3d5c4c5de7722be8fAdam Lesinski#endif
35ad751224401564dcc8338df3d5c4c5de7722be8fAdam Lesinski
36282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
37282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Show version info.  All the cool kids do it.
38282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
39282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doVersion(Bundle* bundle)
40282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
41282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getFileSpecCount() != 0) {
42282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printf("(ignoring extra arguments)\n");
43282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
44ad751224401564dcc8338df3d5c4c5de7722be8fAdam Lesinski    printf("Android Asset Packaging Tool, v0.2-" AAPT_VERSION "\n");
45282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
46282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return 0;
47282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
48282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
49282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
50282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
51282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Open the file read only.  The call fails if the file doesn't exist.
52282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
53282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Returns NULL on failure.
54282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
55282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiZipFile* openReadOnly(const char* fileName)
56282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
57282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ZipFile* zip;
58282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t result;
59282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
60282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    zip = new ZipFile;
61282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    result = zip->open(fileName, ZipFile::kOpenReadOnly);
62282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (result != NO_ERROR) {
63282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (result == NAME_NOT_FOUND) {
64282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: '%s' not found\n", fileName);
65282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else if (result == PERMISSION_DENIED) {
66282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: '%s' access denied\n", fileName);
67282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
68282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: failed opening '%s' as Zip file\n",
69282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fileName);
70282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
71282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        delete zip;
72282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NULL;
73282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
74282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
75282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return zip;
76282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
77282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
78282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
79282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Open the file read-write.  The file will be created if it doesn't
80282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * already exist and "okayToCreate" is set.
81282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
82282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Returns NULL on failure.
83282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
84282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiZipFile* openReadWrite(const char* fileName, bool okayToCreate)
85282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
86282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ZipFile* zip = NULL;
87282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t result;
88282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int flags;
89282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
90282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    flags = ZipFile::kOpenReadWrite;
91282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (okayToCreate) {
92282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        flags |= ZipFile::kOpenCreate;
93282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
94282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
95282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    zip = new ZipFile;
96282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    result = zip->open(fileName, flags);
97282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (result != NO_ERROR) {
98282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        delete zip;
99282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        zip = NULL;
100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail:
104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return zip;
105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Return a short string describing the compression method.
110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiconst char* compressionName(int method)
112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (method == ZipEntry::kCompressStored) {
114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return "Stored";
115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else if (method == ZipEntry::kCompressDeflated) {
116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return "Deflated";
117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return "Unknown";
119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Return the percent reduction in size (0% == no compression).
124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint calcPercent(long uncompressedLen, long compressedLen)
126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (!uncompressedLen) {
128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return 0;
129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return (int) (100.0 - (compressedLen * 100.0) / uncompressedLen + 0.5);
131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Handle the "list" command, which can be a simple file dump or
136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * a verbose listing.
137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * The verbose listing closely matches the output of the Info-ZIP "unzip"
139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * command.
140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doList(Bundle* bundle)
142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int result = 1;
144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ZipFile* zip = NULL;
145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const ZipEntry* entry;
146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    long totalUncLen, totalCompLen;
147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char* zipFileName;
148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getFileSpecCount() != 1) {
150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: specify zip file name (only)\n");
151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    zipFileName = bundle->getFileSpecEntry(0);
154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    zip = openReadOnly(zipFileName);
156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (zip == NULL) {
157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int count, i;
161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getVerbose()) {
163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printf("Archive:  %s\n", zipFileName);
164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printf(
165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            " Length   Method    Size  Ratio   Offset      Date  Time  CRC-32    Name\n");
166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printf(
167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            "--------  ------  ------- -----  -------      ----  ----  ------    ----\n");
168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    totalUncLen = totalCompLen = 0;
171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    count = zip->getNumEntries();
173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (i = 0; i < count; i++) {
174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        entry = zip->getEntryByIndex(i);
175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (bundle->getVerbose()) {
176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            char dateBuf[32];
177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            time_t when;
178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            when = entry->getModWhen();
180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            strftime(dateBuf, sizeof(dateBuf), "%m-%d-%y %H:%M",
181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                localtime(&when));
182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("%8ld  %-7.7s %7ld %3d%%  %8zd  %s  %08lx  %s\n",
184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                (long) entry->getUncompressedLen(),
185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                compressionName(entry->getCompressionMethod()),
186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                (long) entry->getCompressedLen(),
187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                calcPercent(entry->getUncompressedLen(),
188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            entry->getCompressedLen()),
189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                (size_t) entry->getLFHOffset(),
190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                dateBuf,
191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                entry->getCRC32(),
192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                entry->getFileName());
193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("%s\n", entry->getFileName());
195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        totalUncLen += entry->getUncompressedLen();
198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        totalCompLen += entry->getCompressedLen();
199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getVerbose()) {
202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printf(
203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        "--------          -------  ---                            -------\n");
204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printf("%8ld          %7ld  %2d%%                            %d files\n",
205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            totalUncLen,
206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            totalCompLen,
207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            calcPercent(totalUncLen, totalCompLen),
208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            zip->getNumEntries());
209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getAndroidList()) {
212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        AssetManager assets;
213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!assets.addAssetPath(String8(zipFileName), NULL)) {
214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: list -a failed because assets could not be loaded\n");
215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const ResTable& res = assets.getResources(false);
219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (&res == NULL) {
220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("\nNo resource table found.\n");
221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#ifndef HAVE_ANDROID_OS
223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("\nResource table:\n");
224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            res.print(false);
225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif
226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Asset* manifestAsset = assets.openNonAsset("AndroidManifest.xml",
229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                   Asset::ACCESS_BUFFER);
230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (manifestAsset == NULL) {
231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("\nNo AndroidManifest.xml found.\n");
232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("\nAndroid manifest:\n");
234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ResXMLTree tree;
235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            tree.setTo(manifestAsset->getBuffer(true),
236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       manifestAsset->getLength());
237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printXMLBlock(&tree);
238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        delete manifestAsset;
240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    result = 0;
243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail:
245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    delete zip;
246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return result;
247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
249ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinskistatic void printResolvedResourceAttribute(const ResTable& resTable, const ResXMLTree& tree,
25076327314d2238e105f8b94909f9c0cf85caca318Maurice Chu        uint32_t attrRes, String8 attrLabel, String8* outError)
25176327314d2238e105f8b94909f9c0cf85caca318Maurice Chu{
25276327314d2238e105f8b94909f9c0cf85caca318Maurice Chu    Res_value value;
253ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski    AaptXml::getResolvedResourceAttribute(resTable, tree, attrRes, &value, outError);
25476327314d2238e105f8b94909f9c0cf85caca318Maurice Chu    if (*outError != "") {
25576327314d2238e105f8b94909f9c0cf85caca318Maurice Chu        *outError = "error print resolved resource attribute";
25676327314d2238e105f8b94909f9c0cf85caca318Maurice Chu        return;
25776327314d2238e105f8b94909f9c0cf85caca318Maurice Chu    }
25876327314d2238e105f8b94909f9c0cf85caca318Maurice Chu    if (value.dataType == Res_value::TYPE_STRING) {
259ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski        String8 result = AaptXml::getResolvedAttribute(resTable, tree, attrRes, outError);
2602675f769673f69b0661ddee346292f25cb30a296Maurice Chu        printf("%s='%s'", attrLabel.string(),
2612675f769673f69b0661ddee346292f25cb30a296Maurice Chu                ResTable::normalizeForOutput(result.string()).string());
26276327314d2238e105f8b94909f9c0cf85caca318Maurice Chu    } else if (Res_value::TYPE_FIRST_INT <= value.dataType &&
26376327314d2238e105f8b94909f9c0cf85caca318Maurice Chu            value.dataType <= Res_value::TYPE_LAST_INT) {
26476327314d2238e105f8b94909f9c0cf85caca318Maurice Chu        printf("%s='%d'", attrLabel.string(), value.data);
26576327314d2238e105f8b94909f9c0cf85caca318Maurice Chu    } else {
26676327314d2238e105f8b94909f9c0cf85caca318Maurice Chu        printf("%s='0x%x'", attrLabel.string(), (int)value.data);
26776327314d2238e105f8b94909f9c0cf85caca318Maurice Chu    }
26876327314d2238e105f8b94909f9c0cf85caca318Maurice Chu}
26976327314d2238e105f8b94909f9c0cf85caca318Maurice Chu
270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// These are attribute resource constants for the platform, as found
271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// in android.R.attr
272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskienum {
273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    LABEL_ATTR = 0x01010001,
274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ICON_ATTR = 0x01010002,
275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    NAME_ATTR = 0x01010003,
276a5018c900f126ee8424c82497f32983873db741bAdam Lesinski    PERMISSION_ATTR = 0x01010006,
2779d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski    EXPORTED_ATTR = 0x01010010,
2789d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski    GRANT_URI_PERMISSIONS_ATTR = 0x0101001b,
27994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    RESOURCE_ATTR = 0x01010025,
280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    DEBUGGABLE_ATTR = 0x0101000f,
281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    VALUE_ATTR = 0x01010024,
282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    VERSION_CODE_ATTR = 0x0101021b,
283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    VERSION_NAME_ATTR = 0x0101021c,
284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    SCREEN_ORIENTATION_ATTR = 0x0101001e,
285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    MIN_SDK_VERSION_ATTR = 0x0101020c,
286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    MAX_SDK_VERSION_ATTR = 0x01010271,
287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    REQ_TOUCH_SCREEN_ATTR = 0x01010227,
288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    REQ_KEYBOARD_TYPE_ATTR = 0x01010228,
289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    REQ_HARD_KEYBOARD_ATTR = 0x01010229,
290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    REQ_NAVIGATION_ATTR = 0x0101022a,
291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    REQ_FIVE_WAY_NAV_ATTR = 0x01010232,
292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    TARGET_SDK_VERSION_ATTR = 0x01010270,
293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    TEST_ONLY_ATTR = 0x01010272,
294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ANY_DENSITY_ATTR = 0x0101026c,
295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    GL_ES_VERSION_ATTR = 0x01010281,
296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    SMALL_SCREEN_ATTR = 0x01010284,
297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    NORMAL_SCREEN_ATTR = 0x01010285,
298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    LARGE_SCREEN_ATTR = 0x01010286,
299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    XLARGE_SCREEN_ATTR = 0x010102bf,
300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    REQUIRED_ATTR = 0x0101028e,
301caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski    INSTALL_LOCATION_ATTR = 0x010102b7,
302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    SCREEN_SIZE_ATTR = 0x010102ca,
303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    SCREEN_DENSITY_ATTR = 0x010102cb,
304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    REQUIRES_SMALLEST_WIDTH_DP_ATTR = 0x01010364,
305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    COMPATIBLE_WIDTH_LIMIT_DP_ATTR = 0x01010365,
306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    LARGEST_WIDTH_LIMIT_DP_ATTR = 0x01010366,
307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    PUBLIC_KEY_ATTR = 0x010103a6,
30894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    CATEGORY_ATTR = 0x010103e8,
3090a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn    BANNER_ATTR = 0x10103f2,
310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski};
311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3122675f769673f69b0661ddee346292f25cb30a296Maurice ChuString8 getComponentName(String8 &pkgName, String8 &componentName) {
313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t idx = componentName.find(".");
314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String8 retStr(pkgName);
315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (idx == 0) {
316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        retStr += componentName;
317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else if (idx < 0) {
318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        retStr += ".";
319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        retStr += componentName;
320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
3212675f769673f69b0661ddee346292f25cb30a296Maurice Chu        return componentName;
322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3232675f769673f69b0661ddee346292f25cb30a296Maurice Chu    return retStr;
324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3269cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinskistatic void printCompatibleScreens(ResXMLTree& tree, String8* outError) {
327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t len;
328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ResXMLTree::event_code_t code;
329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int depth = 0;
330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool first = true;
331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    printf("compatible-screens:");
332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (code == ResXMLTree::END_TAG) {
334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            depth--;
335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (depth < 0) {
336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                break;
337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (code != ResXMLTree::START_TAG) {
341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        depth++;
3449cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski        const char16_t* ctag16 = tree.getElementName(&len);
3459cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski        if (ctag16 == NULL) {
3469cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski            *outError = "failed to get XML element name (bad string pool)";
3479cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski            return;
3489cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski        }
3499cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski        String8 tag(ctag16);
350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (tag == "screen") {
351ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski            int32_t screenSize = AaptXml::getIntegerAttribute(tree,
352ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                    SCREEN_SIZE_ATTR);
353ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski            int32_t screenDensity = AaptXml::getIntegerAttribute(tree,
354ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                    SCREEN_DENSITY_ATTR);
355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (screenSize > 0 && screenDensity > 0) {
356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!first) {
357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    printf(",");
358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                first = false;
360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("'%d/%d'", screenSize, screenDensity);
361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    printf("\n");
365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
36758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinskistatic void printUsesPermission(const String8& name, bool optional=false, int maxSdkVersion=-1) {
36858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski    printf("uses-permission: name='%s'", ResTable::normalizeForOutput(name.string()).string());
36958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski    if (maxSdkVersion != -1) {
37058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski         printf(" maxSdkVersion='%d'", maxSdkVersion);
37158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski    }
37258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski    printf("\n");
37358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski
37458f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski    if (optional) {
37558f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski        printf("optional-permission: name='%s'",
37658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                ResTable::normalizeForOutput(name.string()).string());
37758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski        if (maxSdkVersion != -1) {
37858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski            printf(" maxSdkVersion='%d'", maxSdkVersion);
37958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski        }
38058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski        printf("\n");
38158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski    }
38258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski}
38358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski
38458f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinskistatic void printUsesImpliedPermission(const String8& name, const String8& reason) {
38558f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski    printf("uses-implied-permission: name='%s' reason='%s'\n",
38658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski            ResTable::normalizeForOutput(name.string()).string(),
38758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski            ResTable::normalizeForOutput(reason.string()).string());
38858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski}
38958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski
39094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam LesinskiVector<String8> getNfcAidCategories(AssetManager& assets, String8 xmlPath, bool offHost,
39194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski        String8 *outError = NULL)
39294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski{
39394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    Asset* aidAsset = assets.openNonAsset(xmlPath, Asset::ACCESS_BUFFER);
39494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    if (aidAsset == NULL) {
39594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski        if (outError != NULL) *outError = "xml resource does not exist";
39694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski        return Vector<String8>();
39794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    }
39894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
39994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    const String8 serviceTagName(offHost ? "offhost-apdu-service" : "host-apdu-service");
40094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
40194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    bool withinApduService = false;
40294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    Vector<String8> categories;
40394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
40494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    String8 error;
40594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    ResXMLTree tree;
40694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    tree.setTo(aidAsset->getBuffer(true), aidAsset->getLength());
40794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
40894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    size_t len;
40994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    int depth = 0;
41094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    ResXMLTree::event_code_t code;
41194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
41294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski        if (code == ResXMLTree::END_TAG) {
41394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            depth--;
4149cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski            const char16_t* ctag16 = tree.getElementName(&len);
4159cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski            if (ctag16 == NULL) {
4169cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                *outError = "failed to get XML element name (bad string pool)";
4179cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                return Vector<String8>();
4189cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski            }
4199cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski            String8 tag(ctag16);
42094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
42194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            if (depth == 0 && tag == serviceTagName) {
42294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                withinApduService = false;
42394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            }
42494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
42594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski        } else if (code == ResXMLTree::START_TAG) {
42694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            depth++;
4279cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski            const char16_t* ctag16 = tree.getElementName(&len);
4289cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski            if (ctag16 == NULL) {
4299cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                *outError = "failed to get XML element name (bad string pool)";
4309cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                return Vector<String8>();
4319cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski            }
4329cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski            String8 tag(ctag16);
43394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
43494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            if (depth == 1) {
43594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                if (tag == serviceTagName) {
43694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    withinApduService = true;
43794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                }
43894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            } else if (depth == 2 && withinApduService) {
43994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                if (tag == "aid-group") {
440ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                    String8 category = AaptXml::getAttribute(tree, CATEGORY_ATTR, &error);
44194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    if (error != "") {
44294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        if (outError != NULL) *outError = error;
44394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        return Vector<String8>();
44494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    }
44594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
44694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    categories.add(category);
44794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                }
44894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            }
44994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski        }
45094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    }
45194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    aidAsset->close();
45294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    return categories;
45394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski}
45494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
4559d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinskistatic void printComponentPresence(const char* componentName) {
4569d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski    printf("provides-component:'%s'\n", componentName);
4579d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski}
4589d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski
4592c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski/**
4602c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * Represents a feature that has been automatically added due to
4612c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * a pre-requisite or some other reason.
4622c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski */
4632c72b6822debb08fe997926eedc110f62d287d34Adam Lesinskistruct ImpliedFeature {
4642c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    /**
4652c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski     * Name of the implied feature.
4662c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski     */
4672c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    String8 name;
4682c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
4692c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    /**
4702c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski     * List of human-readable reasons for why this feature was implied.
4712c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski     */
4722c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    SortedVector<String8> reasons;
4732c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski};
4742c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
4752c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski/**
4762c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * Represents a <feature-group> tag in the AndroidManifest.xml
4772c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski */
4782c72b6822debb08fe997926eedc110f62d287d34Adam Lesinskistruct FeatureGroup {
479d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski    FeatureGroup() : openGLESVersion(-1) {}
480d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski
4812c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    /**
4822c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski     * Human readable label
4832c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski     */
4842c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    String8 label;
4852c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
4862c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    /**
4872c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski     * Explicit features defined in the group
4882c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski     */
4892c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    KeyedVector<String8, bool> features;
490d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski
491d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski    /**
492d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski     * OpenGL ES version required
493d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski     */
494d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski    int openGLESVersion;
4952c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski};
4962c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
4972c72b6822debb08fe997926eedc110f62d287d34Adam Lesinskistatic void addImpliedFeature(KeyedVector<String8, ImpliedFeature>* impliedFeatures,
4982c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        const char* name, const char* reason) {
4992c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    String8 name8(name);
5002c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    ssize_t idx = impliedFeatures->indexOfKey(name8);
5012c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    if (idx < 0) {
5022c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        idx = impliedFeatures->add(name8, ImpliedFeature());
5032c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        impliedFeatures->editValueAt(idx).name = name8;
5042c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    }
5052c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    impliedFeatures->editValueAt(idx).reasons.add(String8(reason));
5062c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski}
5072c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
5082c72b6822debb08fe997926eedc110f62d287d34Adam Lesinskistatic void printFeatureGroup(const FeatureGroup& grp,
5092c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        const KeyedVector<String8, ImpliedFeature>* impliedFeatures = NULL) {
5102c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    printf("feature-group: label='%s'\n", grp.label.string());
5112c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
512d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski    if (grp.openGLESVersion > 0) {
513d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski        printf("  uses-gl-es: '0x%x'\n", grp.openGLESVersion);
514d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski    }
515d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski
5162c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    const size_t numFeatures = grp.features.size();
5172c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    for (size_t i = 0; i < numFeatures; i++) {
5182c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        if (!grp.features[i]) {
5192c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski            continue;
5202c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        }
5212c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
5222c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        const String8& featureName = grp.features.keyAt(i);
5232c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        printf("  uses-feature: name='%s'\n",
5242c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                ResTable::normalizeForOutput(featureName.string()).string());
5252c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    }
5262c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
5272c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    const size_t numImpliedFeatures =
5282c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        (impliedFeatures != NULL) ? impliedFeatures->size() : 0;
5292c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    for (size_t i = 0; i < numImpliedFeatures; i++) {
5302c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        const ImpliedFeature& impliedFeature = impliedFeatures->valueAt(i);
5312c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        if (grp.features.indexOfKey(impliedFeature.name) >= 0) {
5322c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski            // The feature is explicitly set, no need to use implied
5332c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski            // definition.
5342c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski            continue;
5352c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        }
5362c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
5372c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        String8 printableFeatureName(ResTable::normalizeForOutput(
5382c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                    impliedFeature.name.string()));
5392c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        printf("  uses-feature: name='%s'\n", printableFeatureName.string());
5402c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        printf("  uses-implied-feature: name='%s' reason='",
5412c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                printableFeatureName.string());
5422c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        const size_t numReasons = impliedFeature.reasons.size();
5432c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        for (size_t j = 0; j < numReasons; j++) {
5442c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski            printf("%s", impliedFeature.reasons[j].string());
5452c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski            if (j + 2 < numReasons) {
5462c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                printf(", ");
5472c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski            } else if (j + 1 < numReasons) {
5482c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                printf(", and ");
5492c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski            }
5502c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        }
5512c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        printf("'\n");
5522c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    }
5532c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski}
5542c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
5552c72b6822debb08fe997926eedc110f62d287d34Adam Lesinskistatic void addParentFeatures(FeatureGroup* grp, const String8& name) {
5562c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    if (name == "android.hardware.camera.autofocus" ||
5572c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski            name == "android.hardware.camera.flash") {
5582c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        grp->features.add(String8("android.hardware.camera"), true);
5592c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    } else if (name == "android.hardware.location.gps" ||
5602c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski            name == "android.hardware.location.network") {
5612c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        grp->features.add(String8("android.hardware.location"), true);
5622c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    } else if (name == "android.hardware.touchscreen.multitouch") {
5632c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        grp->features.add(String8("android.hardware.touchscreen"), true);
5642c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    } else if (name == "android.hardware.touchscreen.multitouch.distinct") {
5652c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        grp->features.add(String8("android.hardware.touchscreen.multitouch"), true);
5662c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        grp->features.add(String8("android.hardware.touchscreen"), true);
567d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski    } else if (name == "android.hardware.opengles.aep") {
568d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski        const int openGLESVersion31 = 0x00030001;
569d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski        if (openGLESVersion31 > grp->openGLESVersion) {
570d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski            grp->openGLESVersion = openGLESVersion31;
571d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski        }
5722c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    }
5732c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski}
5742c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Handle the "dump" command, to extract select data from an archive.
577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiextern char CONSOLE_DATA[2925]; // see EOF
579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doDump(Bundle* bundle)
580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t result = UNKNOWN_ERROR;
582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getFileSpecCount() < 1) {
584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: no dump option specified\n");
585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return 1;
586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getFileSpecCount() < 2) {
589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: no dump file specified\n");
590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return 1;
591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
593282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char* option = bundle->getFileSpecEntry(0);
594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char* filename = bundle->getFileSpecEntry(1);
595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    AssetManager assets;
597f85e41f29a0e9313c2d4725f9d9648591ea49f3bNarayan Kamath    int32_t assetsCookie;
598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (!assets.addAssetPath(String8(filename), &assetsCookie)) {
599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: dump failed because assets could not be loaded\n");
600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return 1;
601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Make a dummy config for retrieving resources...  we need to supply
604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // non-default values for some configs so that we can retrieve resources
605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // in the app that don't have a default.  The most important of these is
606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // the API version because key resources like icons will have an implicit
607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // version if they are using newer config types like density.
608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ResTable_config config;
60991447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath    memset(&config, 0, sizeof(ResTable_config));
610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    config.language[0] = 'e';
611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    config.language[1] = 'n';
612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    config.country[0] = 'U';
613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    config.country[1] = 'S';
614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    config.orientation = ResTable_config::ORIENTATION_PORT;
615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    config.density = ResTable_config::DENSITY_MEDIUM;
616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    config.sdkVersion = 10000; // Very high.
617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    config.screenWidthDp = 320;
618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    config.screenHeightDp = 480;
619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    config.smallestScreenWidthDp = 320;
620c2dea8daea2ae0001d56689d96ce1066012b7b40Adam Lesinski    config.screenLayout |= ResTable_config::SCREENSIZE_NORMAL;
621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    assets.setConfiguration(config);
622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const ResTable& res = assets.getResources(false);
624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (&res == NULL) {
625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: dump failed because no resource table was found\n");
62663e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski        return 1;
62725e9d55e964c180ec6e57ba1d977d6c2e1115f5aAdam Lesinski    } else if (res.getError() != NO_ERROR) {
62825e9d55e964c180ec6e57ba1d977d6c2e1115f5aAdam Lesinski        fprintf(stderr, "ERROR: dump failed because the resource table is invalid/corrupt.\n");
62963e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski        return 1;
63063e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski    }
63163e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski
6322cb761e3ddb9d68ab430013e9cd15ecaab9fbc62Adam Lesinski    // The dynamicRefTable can be null if there are no resources for this asset cookie.
6332cb761e3ddb9d68ab430013e9cd15ecaab9fbc62Adam Lesinski    // This fine.
63463e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski    const DynamicRefTable* dynamicRefTable = res.getDynamicRefTableForCookie(assetsCookie);
635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
63663e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski    Asset* asset = NULL;
63763e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski
638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (strcmp("resources", option) == 0) {
639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#ifndef HAVE_ANDROID_OS
640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        res.print(bundle->getValues());
641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif
642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else if (strcmp("strings", option) == 0) {
644282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const ResStringPool* pool = res.getTableStringBlock(0);
645282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printStringPool(pool);
646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else if (strcmp("xmltree", option) == 0) {
648282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (bundle->getFileSpecCount() < 3) {
649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: no dump xmltree resource file specified\n");
650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (int i=2; i<bundle->getFileSpecCount(); i++) {
654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const char* resname = bundle->getFileSpecEntry(i);
65563e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski            ResXMLTree tree(dynamicRefTable);
65663e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski            asset = assets.openNonAsset(assetsCookie, resname, Asset::ACCESS_BUFFER);
657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (asset == NULL) {
658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, "ERROR: dump failed because resource %s found\n", resname);
659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                goto bail;
660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (tree.setTo(asset->getBuffer(true),
663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           asset->getLength()) != NO_ERROR) {
664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, "ERROR: Resource %s is corrupt\n", resname);
665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                goto bail;
666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            tree.restart();
668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printXMLBlock(&tree);
669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            tree.uninit();
670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            delete asset;
671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            asset = NULL;
672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else if (strcmp("xmlstrings", option) == 0) {
675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (bundle->getFileSpecCount() < 3) {
676282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: no dump xmltree resource file specified\n");
677282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
679282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
680282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (int i=2; i<bundle->getFileSpecCount(); i++) {
681282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const char* resname = bundle->getFileSpecEntry(i);
68263e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski            asset = assets.openNonAsset(assetsCookie, resname, Asset::ACCESS_BUFFER);
683282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (asset == NULL) {
684282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, "ERROR: dump failed because resource %s found\n", resname);
685282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                goto bail;
686282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
687282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
68863e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski            ResXMLTree tree(dynamicRefTable);
689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (tree.setTo(asset->getBuffer(true),
690282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           asset->getLength()) != NO_ERROR) {
691282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, "ERROR: Resource %s is corrupt\n", resname);
692282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                goto bail;
693282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
694282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printStringPool(&tree.getStrings());
695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            delete asset;
696282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            asset = NULL;
697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
70063e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski        asset = assets.openNonAsset(assetsCookie, "AndroidManifest.xml", Asset::ACCESS_BUFFER);
701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (asset == NULL) {
702282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: dump failed because no AndroidManifest.xml found\n");
703282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
704282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
705282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
70663e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski        ResXMLTree tree(dynamicRefTable);
707282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (tree.setTo(asset->getBuffer(true),
708282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       asset->getLength()) != NO_ERROR) {
709282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: AndroidManifest.xml is corrupt\n");
710282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
711282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        tree.restart();
713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
714282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (strcmp("permissions", option) == 0) {
715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            size_t len;
716282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ResXMLTree::event_code_t code;
717282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int depth = 0;
718282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
719282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (code == ResXMLTree::END_TAG) {
720282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    depth--;
721282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
722282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
723282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (code != ResXMLTree::START_TAG) {
724282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
725282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
726282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                depth++;
7279cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                const char16_t* ctag16 = tree.getElementName(&len);
7289cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                if (ctag16 == NULL) {
7299cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                    fprintf(stderr, "ERROR: failed to get XML element name (bad string pool)\n");
7309cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                    goto bail;
7319cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                }
7329cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                String8 tag(ctag16);
733282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                //printf("Depth %d tag %s\n", depth, tag.string());
734282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (depth == 1) {
735282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (tag != "manifest") {
736282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n");
737282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        goto bail;
738282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
739ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                    String8 pkg = AaptXml::getAttribute(tree, NULL, "package", NULL);
7402675f769673f69b0661ddee346292f25cb30a296Maurice Chu                    printf("package: %s\n", ResTable::normalizeForOutput(pkg.string()).string());
741282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else if (depth == 2 && tag == "permission") {
742282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8 error;
743ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                    String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
744282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (error != "") {
745282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        fprintf(stderr, "ERROR: %s\n", error.string());
746282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        goto bail;
747282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
7482675f769673f69b0661ddee346292f25cb30a296Maurice Chu                    printf("permission: %s\n",
7492675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            ResTable::normalizeForOutput(name.string()).string());
750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else if (depth == 2 && tag == "uses-permission") {
751282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8 error;
752ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                    String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
753282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (error != "") {
754282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        fprintf(stderr, "ERROR: %s\n", error.string());
755282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        goto bail;
756282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
75758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesPermission(name,
758ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            AaptXml::getIntegerAttribute(tree, REQUIRED_ATTR, 1) == 0,
759ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            AaptXml::getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR));
760282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
761282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
762282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else if (strcmp("badging", option) == 0) {
763282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Vector<String8> locales;
764282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            res.getLocales(&locales);
765282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
766282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Vector<ResTable_config> configs;
767282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            res.getConfigurations(&configs);
768282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            SortedVector<int> densities;
769282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t NC = configs.size();
770282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t i=0; i<NC; i++) {
771282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                int dens = configs[i].density;
772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (dens == 0) {
773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    dens = 160;
774282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                densities.add(dens);
776282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            size_t len;
779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ResXMLTree::event_code_t code;
780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int depth = 0;
781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 error;
782282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool withinActivity = false;
783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool isMainActivity = false;
784282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool isLauncherActivity = false;
7850a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn            bool isLeanbackLauncherActivity = false;
786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool isSearchable = false;
787282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool withinApplication = false;
788ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright            bool withinSupportsInput = false;
7892c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski            bool withinFeatureGroup = false;
790282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool withinReceiver = false;
791282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool withinService = false;
7929d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool withinProvider = false;
793282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool withinIntentFilter = false;
794282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasMainActivity = false;
795282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasOtherActivities = false;
796282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasOtherReceivers = false;
797282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasOtherServices = false;
7989d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool hasIntentFilter = false;
7999d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski
800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasWallpaperService = false;
801282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasImeService = false;
802a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool hasAccessibilityService = false;
803a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool hasPrintService = false;
804282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasWidgetReceivers = false;
805a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool hasDeviceAdminReceiver = false;
80694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            bool hasPaymentService = false;
8079d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool hasDocumentsProvider = false;
8089d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool hasCameraActivity = false;
8099d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool hasCameraSecureActivity = false;
8109d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool hasLauncher = false;
8119d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool hasNotificationListenerService = false;
812eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock            bool hasDreamService = false;
8139d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski
814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool actMainActivity = false;
815282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool actWidgetReceivers = false;
816a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool actDeviceAdminEnabled = false;
817282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool actImeService = false;
818282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool actWallpaperService = false;
819a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool actAccessibilityService = false;
820a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool actPrintService = false;
82194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            bool actHostApduService = false;
82294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            bool actOffHostApduService = false;
8239d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool actDocumentsProvider = false;
8249d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool actNotificationListenerService = false;
825eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock            bool actDreamService = false;
8269d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool actCamera = false;
8279d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool actCameraSecure = false;
8289d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool catLauncher = false;
82994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            bool hasMetaHostPaymentCategory = false;
83094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            bool hasMetaOffHostPaymentCategory = false;
831a5018c900f126ee8424c82497f32983873db741bAdam Lesinski
832a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            // These permissions are required by services implementing services
833a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            // the system binds to (IME, Accessibility, PrintServices, etc.)
834a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool hasBindDeviceAdminPermission = false;
835a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool hasBindInputMethodPermission = false;
836a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool hasBindAccessibilityServicePermission = false;
837a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool hasBindPrintServicePermission = false;
83894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            bool hasBindNfcServicePermission = false;
8399d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool hasRequiredSafAttributes = false;
8409d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool hasBindNotificationListenerServicePermission = false;
841eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock            bool hasBindDreamServicePermission = false;
842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
843282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // These two implement the implicit permissions that are granted
844282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // to pre-1.6 applications.
845282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasWriteExternalStoragePermission = false;
846282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasReadPhoneStatePermission = false;
847282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
848282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // If an app requests write storage, they will also get read storage.
849282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasReadExternalStoragePermission = false;
850282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
851282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Implement transition to read and write call log.
852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasReadContactsPermission = false;
853282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasWriteContactsPermission = false;
854282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasReadCallLogPermission = false;
855282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasWriteCallLogPermission = false;
856282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
857e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski            // If an app declares itself as multiArch, we report the
858e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski            // native libraries differently.
859e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski            bool hasMultiArch = false;
860e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski
861282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // This next group of variables is used to implement a group of
862282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // backward-compatibility heuristics necessitated by the addition of
863282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // some new uses-feature constants in 2.1 and 2.2. In most cases, the
864282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // heuristic is "if an app requests a permission but doesn't explicitly
865282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // request the corresponding <uses-feature>, presume it's there anyway".
8662c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
867282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // 2.2 also added some other features that apps can request, but that
868282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // have no corresponding permission, so we cannot implement any
869282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // back-compatibility heuristic for them. The below are thus unnecessary
870282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // (but are retained here for documentary purposes.)
871282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //bool specCompassFeature = false;
872282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //bool specAccelerometerFeature = false;
873282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //bool specProximityFeature = false;
874282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //bool specAmbientLightFeature = false;
875282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //bool specLiveWallpaperFeature = false;
876282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
877282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int targetSdk = 0;
878282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int smallScreen = 1;
879282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int normalScreen = 1;
880282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int largeScreen = 1;
881282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int xlargeScreen = 1;
882282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int anyDensity = 1;
883282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int requiresSmallestWidthDp = 0;
884282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int compatibleWidthLimitDp = 0;
885282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int largestWidthLimitDp = 0;
886282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 pkg;
887282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 activityName;
888282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 activityLabel;
889282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 activityIcon;
8900a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn            String8 activityBanner;
891282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 receiverName;
892282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 serviceName;
893ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright            Vector<String8> supportedInput;
8942c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
8952c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski            FeatureGroup commonFeatures;
8962c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski            Vector<FeatureGroup> featureGroups;
8972c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski            KeyedVector<String8, ImpliedFeature> impliedFeatures;
8982c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
899282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
900282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (code == ResXMLTree::END_TAG) {
901282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    depth--;
902282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (depth < 2) {
903ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        if (withinSupportsInput && !supportedInput.isEmpty()) {
904ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            printf("supports-input: '");
905ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            const size_t N = supportedInput.size();
906ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            for (size_t i=0; i<N; i++) {
9072675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                printf("%s", ResTable::normalizeForOutput(
9082675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                        supportedInput[i].string()).string());
909ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                if (i != N - 1) {
910ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                    printf("' '");
911ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                } else {
912ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                    printf("'\n");
913ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                }
914ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
915ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            supportedInput.clear();
916ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        }
917282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        withinApplication = false;
918ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        withinSupportsInput = false;
9192c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                        withinFeatureGroup = false;
920282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (depth < 3) {
9210a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                        if (withinActivity && isMainActivity) {
9222675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            String8 aName(getComponentName(pkg, activityName));
9230a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                            if (isLauncherActivity) {
9240a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                printf("launchable-activity:");
9259eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                if (aName.length() > 0) {
9269eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                    printf(" name='%s' ",
9279eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                            ResTable::normalizeForOutput(aName.string()).string());
9280a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                }
9290a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                printf(" label='%s' icon='%s'\n",
9309eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                        ResTable::normalizeForOutput(activityLabel.string()).string(),
9319eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                        ResTable::normalizeForOutput(activityIcon.string()).string());
9320a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                            }
9330a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                            if (isLeanbackLauncherActivity) {
9340a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                printf("leanback-launchable-activity:");
9359eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                if (aName.length() > 0) {
9369eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                    printf(" name='%s' ",
9379eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                            ResTable::normalizeForOutput(aName.string()).string());
9380a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                }
9390a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                printf(" label='%s' icon='%s' banner='%s'\n",
9409eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                        ResTable::normalizeForOutput(activityLabel.string()).string(),
9419eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                        ResTable::normalizeForOutput(activityIcon.string()).string(),
9429eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                        ResTable::normalizeForOutput(activityBanner.string()).string());
943282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
944282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
945282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (!hasIntentFilter) {
946282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            hasOtherActivities |= withinActivity;
947282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            hasOtherReceivers |= withinReceiver;
948282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            hasOtherServices |= withinService;
94994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        } else {
95094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            if (withinService) {
95194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                hasPaymentService |= (actHostApduService && hasMetaHostPaymentCategory &&
95294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                        hasBindNfcServicePermission);
95394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                hasPaymentService |= (actOffHostApduService && hasMetaOffHostPaymentCategory &&
95494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                        hasBindNfcServicePermission);
95594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            }
956282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
957282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        withinActivity = false;
958282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        withinService = false;
959282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        withinReceiver = false;
9609d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                        withinProvider = false;
961282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasIntentFilter = false;
9620a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                        isMainActivity = isLauncherActivity = isLeanbackLauncherActivity = false;
963282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (depth < 4) {
964282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (withinIntentFilter) {
965282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (withinActivity) {
966282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasMainActivity |= actMainActivity;
9679d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                hasLauncher |= catLauncher;
9689d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                hasCameraActivity |= actCamera;
9699d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                hasCameraSecureActivity |= actCameraSecure;
9709d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                hasOtherActivities |= !actMainActivity && !actCamera && !actCameraSecure;
971282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (withinReceiver) {
972282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasWidgetReceivers |= actWidgetReceivers;
973a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                hasDeviceAdminReceiver |= (actDeviceAdminEnabled &&
974a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                        hasBindDeviceAdminPermission);
975a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                hasOtherReceivers |= (!actWidgetReceivers && !actDeviceAdminEnabled);
976282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (withinService) {
977282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasImeService |= actImeService;
978282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasWallpaperService |= actWallpaperService;
979a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                hasAccessibilityService |= (actAccessibilityService &&
980a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                        hasBindAccessibilityServicePermission);
981a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                hasPrintService |= (actPrintService && hasBindPrintServicePermission);
9829d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                hasNotificationListenerService |= actNotificationListenerService &&
9839d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                        hasBindNotificationListenerServicePermission;
984eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock                                hasDreamService |= actDreamService && hasBindDreamServicePermission;
985a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                hasOtherServices |= (!actImeService && !actWallpaperService &&
98694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                        !actAccessibilityService && !actPrintService &&
9879d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                        !actHostApduService && !actOffHostApduService &&
9889d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                        !actNotificationListenerService);
9899d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            } else if (withinProvider) {
9909d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                hasDocumentsProvider |= actDocumentsProvider && hasRequiredSafAttributes;
991282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
992282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
993282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        withinIntentFilter = false;
994282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
995282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
996282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
997282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (code != ResXMLTree::START_TAG) {
998282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
999282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1000282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                depth++;
10019cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski
10029cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                const char16_t* ctag16 = tree.getElementName(&len);
10039cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                if (ctag16 == NULL) {
10049cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                    fprintf(stderr, "ERROR: failed to get XML element name (bad string pool)\n");
10059cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                    goto bail;
10069cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                }
10079cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                String8 tag(ctag16);
1008282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                //printf("Depth %d,  %s\n", depth, tag.string());
1009282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (depth == 1) {
1010282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (tag != "manifest") {
1011282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n");
1012282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        goto bail;
1013282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1014ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                    pkg = AaptXml::getAttribute(tree, NULL, "package", NULL);
10152675f769673f69b0661ddee346292f25cb30a296Maurice Chu                    printf("package: name='%s' ",
10162675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            ResTable::normalizeForOutput(pkg.string()).string());
1017ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                    int32_t versionCode = AaptXml::getIntegerAttribute(tree, VERSION_CODE_ATTR,
1018ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            &error);
1019282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (error != "") {
1020ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        fprintf(stderr, "ERROR getting 'android:versionCode' attribute: %s\n",
1021ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                error.string());
1022282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        goto bail;
1023282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1024282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (versionCode > 0) {
1025282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        printf("versionCode='%d' ", versionCode);
1026282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else {
1027282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        printf("versionCode='' ");
1028282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1029ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                    String8 versionName = AaptXml::getResolvedAttribute(res, tree,
1030ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            VERSION_NAME_ATTR, &error);
1031282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (error != "") {
1032ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        fprintf(stderr, "ERROR getting 'android:versionName' attribute: %s\n",
1033ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                error.string());
1034282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        goto bail;
1035282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
103625d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski                    printf("versionName='%s'",
10372675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            ResTable::normalizeForOutput(versionName.string()).string());
103825d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski
1039ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                    String8 splitName = AaptXml::getAttribute(tree, NULL, "split");
104025d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski                    if (!splitName.isEmpty()) {
104125d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski                        printf(" split='%s'", ResTable::normalizeForOutput(
104225d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski                                    splitName.string()).string());
104325d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski                    }
1044ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski
10455283faba4a75a4d1fd9990637d22768e423895e3Adam Lesinski                    String8 platformVersionName = AaptXml::getAttribute(tree, NULL,
10465283faba4a75a4d1fd9990637d22768e423895e3Adam Lesinski                            "platformBuildVersionName");
10475283faba4a75a4d1fd9990637d22768e423895e3Adam Lesinski                    printf(" platformBuildVersionName='%s'", platformVersionName.string());
104825d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski                    printf("\n");
1049caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski
1050ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                    int32_t installLocation = AaptXml::getResolvedIntegerAttribute(res, tree,
1051ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            INSTALL_LOCATION_ATTR, &error);
1052caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                    if (error != "") {
1053caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                        fprintf(stderr, "ERROR getting 'android:installLocation' attribute: %s\n",
1054caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                                error.string());
1055caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                        goto bail;
1056caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                    }
1057caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski
1058caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                    if (installLocation >= 0) {
1059caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                        printf("install-location:'");
1060caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                        switch (installLocation) {
1061caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                            case 0:
1062caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                                printf("auto");
1063caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                                break;
1064caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                            case 1:
1065caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                                printf("internalOnly");
1066caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                                break;
1067caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                            case 2:
1068caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                                printf("preferExternal");
1069caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                                break;
1070caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                            default:
1071caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                                fprintf(stderr, "Invalid installLocation %d\n", installLocation);
1072caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                                goto bail;
1073caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                        }
1074caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                        printf("'\n");
1075caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                    }
1076282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else if (depth == 2) {
1077282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    withinApplication = false;
1078282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (tag == "application") {
1079282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        withinApplication = true;
1080282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1081282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8 label;
1082282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const size_t NL = locales.size();
1083282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        for (size_t i=0; i<NL; i++) {
1084282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            const char* localeStr =  locales[i].string();
1085282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            assets.setLocale(localeStr != NULL ? localeStr : "");
1086ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            String8 llabel = AaptXml::getResolvedAttribute(res, tree, LABEL_ATTR,
1087ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    &error);
1088282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (llabel != "") {
1089282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                if (localeStr == NULL || strlen(localeStr) == 0) {
1090282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    label = llabel;
10912675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                    printf("application-label:'%s'\n",
10922675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                            ResTable::normalizeForOutput(llabel.string()).string());
1093282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                } else {
1094282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    if (label == "") {
1095282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        label = llabel;
1096282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    }
1097282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    printf("application-label-%s:'%s'\n", localeStr,
10982675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                           ResTable::normalizeForOutput(llabel.string()).string());
1099282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                }
1100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ResTable_config tmpConfig = config;
1104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const size_t ND = densities.size();
1105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        for (size_t i=0; i<ND; i++) {
1106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            tmpConfig.density = densities[i];
1107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            assets.setConfiguration(tmpConfig);
1108ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            String8 icon = AaptXml::getResolvedAttribute(res, tree, ICON_ATTR,
1109ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    &error);
1110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (icon != "") {
11112675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                printf("application-icon-%d:'%s'\n", densities[i],
11122675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                        ResTable::normalizeForOutput(icon.string()).string());
1113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        assets.setConfiguration(config);
1116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1117ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        String8 icon = AaptXml::getResolvedAttribute(res, tree, ICON_ATTR, &error);
1118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (error != "") {
1119ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n",
1120ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    error.string());
1121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            goto bail;
1122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1123ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        int32_t testOnly = AaptXml::getIntegerAttribute(tree, TEST_ONLY_ATTR, 0,
1124ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                &error);
1125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (error != "") {
1126ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            fprintf(stderr, "ERROR getting 'android:testOnly' attribute: %s\n",
1127ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    error.string());
1128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            goto bail;
1129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
11302675f769673f69b0661ddee346292f25cb30a296Maurice Chu                        printf("application: label='%s' ",
11312675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                ResTable::normalizeForOutput(label.string()).string());
11322675f769673f69b0661ddee346292f25cb30a296Maurice Chu                        printf("icon='%s'\n", ResTable::normalizeForOutput(icon.string()).string());
1133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (testOnly != 0) {
1134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf("testOnly='%d'\n", testOnly);
1135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1137ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        int32_t debuggable = AaptXml::getResolvedIntegerAttribute(res, tree,
1138ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                DEBUGGABLE_ATTR, 0, &error);
1139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (error != "") {
1140ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            fprintf(stderr, "ERROR getting 'android:debuggable' attribute: %s\n",
1141ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    error.string());
1142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            goto bail;
1143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (debuggable != 0) {
1145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf("application-debuggable\n");
1146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1147e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski
1148e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        // We must search by name because the multiArch flag hasn't been API
1149e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        // frozen yet.
1150e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        int32_t multiArchIndex = tree.indexOfAttribute(RESOURCES_ANDROID_NAMESPACE,
1151e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                                "multiArch");
1152e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        if (multiArchIndex >= 0) {
1153e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                            Res_value value;
1154e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                            if (tree.getAttributeValue(multiArchIndex, &value) != NO_ERROR) {
1155e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                                if (value.dataType >= Res_value::TYPE_FIRST_INT &&
1156e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                                        value.dataType <= Res_value::TYPE_LAST_INT) {
1157e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                                    hasMultiArch = value.data;
1158e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                                }
1159e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                            }
1160e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        }
1161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "uses-sdk") {
1162ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        int32_t code = AaptXml::getIntegerAttribute(tree, MIN_SDK_VERSION_ATTR, &error);
1163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (error != "") {
1164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            error = "";
1165ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            String8 name = AaptXml::getResolvedAttribute(res, tree,
1166ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    MIN_SDK_VERSION_ATTR, &error);
1167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (error != "") {
1168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                fprintf(stderr, "ERROR getting 'android:minSdkVersion' attribute: %s\n",
1169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        error.string());
1170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                goto bail;
1171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (name == "Donut") targetSdk = 4;
11732675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            printf("sdkVersion:'%s'\n",
11742675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                    ResTable::normalizeForOutput(name.string()).string());
1175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else if (code != -1) {
1176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            targetSdk = code;
1177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf("sdkVersion:'%d'\n", code);
1178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1179ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        code = AaptXml::getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR);
1180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (code != -1) {
1181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf("maxSdkVersion:'%d'\n", code);
1182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1183ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        code = AaptXml::getIntegerAttribute(tree, TARGET_SDK_VERSION_ATTR, &error);
1184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (error != "") {
1185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            error = "";
1186ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            String8 name = AaptXml::getResolvedAttribute(res, tree,
1187ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    TARGET_SDK_VERSION_ATTR, &error);
1188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (error != "") {
1189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                fprintf(stderr, "ERROR getting 'android:targetSdkVersion' attribute: %s\n",
1190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        error.string());
1191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                goto bail;
1192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (name == "Donut" && targetSdk < 4) targetSdk = 4;
11942675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            printf("targetSdkVersion:'%s'\n",
11952675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                    ResTable::normalizeForOutput(name.string()).string());
1196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else if (code != -1) {
1197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (targetSdk < code) {
1198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                targetSdk = code;
1199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf("targetSdkVersion:'%d'\n", code);
1201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "uses-configuration") {
1203ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        int32_t reqTouchScreen = AaptXml::getIntegerAttribute(tree,
1204ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                REQ_TOUCH_SCREEN_ATTR, 0);
1205ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        int32_t reqKeyboardType = AaptXml::getIntegerAttribute(tree,
1206ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                REQ_KEYBOARD_TYPE_ATTR, 0);
1207ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        int32_t reqHardKeyboard = AaptXml::getIntegerAttribute(tree,
1208ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                REQ_HARD_KEYBOARD_ATTR, 0);
1209ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        int32_t reqNavigation = AaptXml::getIntegerAttribute(tree,
1210ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                REQ_NAVIGATION_ATTR, 0);
1211ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        int32_t reqFiveWayNav = AaptXml::getIntegerAttribute(tree,
1212ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                REQ_FIVE_WAY_NAV_ATTR, 0);
1213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        printf("uses-configuration:");
1214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (reqTouchScreen != 0) {
1215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf(" reqTouchScreen='%d'", reqTouchScreen);
1216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (reqKeyboardType != 0) {
1218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf(" reqKeyboardType='%d'", reqKeyboardType);
1219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (reqHardKeyboard != 0) {
1221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf(" reqHardKeyboard='%d'", reqHardKeyboard);
1222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (reqNavigation != 0) {
1224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf(" reqNavigation='%d'", reqNavigation);
1225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (reqFiveWayNav != 0) {
1227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf(" reqFiveWayNav='%d'", reqFiveWayNav);
1228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        printf("\n");
1230ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                    } else if (tag == "supports-input") {
1231ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        withinSupportsInput = true;
1232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "supports-screens") {
1233ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        smallScreen = AaptXml::getIntegerAttribute(tree,
1234ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                SMALL_SCREEN_ATTR, 1);
1235ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        normalScreen = AaptXml::getIntegerAttribute(tree,
1236ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                NORMAL_SCREEN_ATTR, 1);
1237ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        largeScreen = AaptXml::getIntegerAttribute(tree,
1238ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                LARGE_SCREEN_ATTR, 1);
1239ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        xlargeScreen = AaptXml::getIntegerAttribute(tree,
1240ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                XLARGE_SCREEN_ATTR, 1);
1241ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        anyDensity = AaptXml::getIntegerAttribute(tree,
1242ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                ANY_DENSITY_ATTR, 1);
1243ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        requiresSmallestWidthDp = AaptXml::getIntegerAttribute(tree,
1244ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                REQUIRES_SMALLEST_WIDTH_DP_ATTR, 0);
1245ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        compatibleWidthLimitDp = AaptXml::getIntegerAttribute(tree,
1246ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                COMPATIBLE_WIDTH_LIMIT_DP_ATTR, 0);
1247ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        largestWidthLimitDp = AaptXml::getIntegerAttribute(tree,
1248ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                LARGEST_WIDTH_LIMIT_DP_ATTR, 0);
12492c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                    } else if (tag == "feature-group") {
12502c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                        withinFeatureGroup = true;
12512c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                        FeatureGroup group;
1252ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        group.label = AaptXml::getResolvedAttribute(res, tree, LABEL_ATTR, &error);
12532c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                        if (error != "") {
12542c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                            fprintf(stderr, "ERROR getting 'android:label' attribute:"
12552c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                    " %s\n", error.string());
12562c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                            goto bail;
12572c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                        }
12582c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                        featureGroups.add(group);
12592c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
1260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "uses-feature") {
1261ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
1262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (name != "" && error == "") {
1263ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            int req = AaptXml::getIntegerAttribute(tree,
1264ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    REQUIRED_ATTR, 1);
1265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
12662c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                            commonFeatures.features.add(name, req);
12672c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                            if (req) {
12682c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                addParentFeatures(&commonFeatures, name);
1269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else {
1271ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            int vers = AaptXml::getIntegerAttribute(tree,
1272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    GL_ES_VERSION_ATTR, &error);
1273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (error == "") {
1274d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                                if (vers > commonFeatures.openGLESVersion) {
1275d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                                    commonFeatures.openGLESVersion = vers;
1276d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                                }
1277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "uses-permission") {
1280ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
1281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (name != "" && error == "") {
1282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (name == "android.permission.CAMERA") {
1283d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                                addImpliedFeature(&impliedFeatures, "android.hardware.camera",
12842c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        String8::format("requested %s permission", name.string())
12852c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        .string());
1286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.ACCESS_FINE_LOCATION") {
12872c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                addImpliedFeature(&impliedFeatures, "android.hardware.location.gps",
12882c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        String8::format("requested %s permission", name.string())
12892c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        .string());
12902c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                addImpliedFeature(&impliedFeatures, "android.hardware.location",
12912c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        String8::format("requested %s permission", name.string())
12922c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        .string());
1293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.ACCESS_MOCK_LOCATION") {
12942c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                addImpliedFeature(&impliedFeatures, "android.hardware.location",
12952c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        String8::format("requested %s permission", name.string())
12962c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        .string());
1297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.ACCESS_COARSE_LOCATION") {
12982c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                addImpliedFeature(&impliedFeatures, "android.hardware.location.network",
12992c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        String8::format("requested %s permission", name.string())
13002c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        .string());
13012c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                addImpliedFeature(&impliedFeatures, "android.hardware.location",
13022c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        String8::format("requested %s permission", name.string())
13032c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        .string());
1304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" ||
1305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.INSTALL_LOCATION_PROVIDER") {
13062c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                addImpliedFeature(&impliedFeatures, "android.hardware.location",
13072c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        String8::format("requested %s permission", name.string())
13082c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        .string());
1309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.BLUETOOTH" ||
1310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.BLUETOOTH_ADMIN") {
13112c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                if (targetSdk > 4) {
13122c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                    addImpliedFeature(&impliedFeatures, "android.hardware.bluetooth",
13132c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                            String8::format("requested %s permission", name.string())
13142c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                            .string());
13152c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                    addImpliedFeature(&impliedFeatures, "android.hardware.bluetooth",
13162c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                            "targetSdkVersion > 4");
13172c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                }
1318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.RECORD_AUDIO") {
13192c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                addImpliedFeature(&impliedFeatures, "android.hardware.microphone",
13202c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        String8::format("requested %s permission", name.string())
13212c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        .string());
1322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.ACCESS_WIFI_STATE" ||
1323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.CHANGE_WIFI_STATE" ||
1324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.CHANGE_WIFI_MULTICAST_STATE") {
13252c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                addImpliedFeature(&impliedFeatures, "android.hardware.wifi",
13262c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        String8::format("requested %s permission", name.string())
13272c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        .string());
1328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.CALL_PHONE" ||
1329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.CALL_PRIVILEGED" ||
1330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.MODIFY_PHONE_STATE" ||
1331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.PROCESS_OUTGOING_CALLS" ||
1332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.READ_SMS" ||
1333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.RECEIVE_SMS" ||
1334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.RECEIVE_MMS" ||
1335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.RECEIVE_WAP_PUSH" ||
1336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.SEND_SMS" ||
1337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.WRITE_APN_SETTINGS" ||
1338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.WRITE_SMS") {
13392c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                addImpliedFeature(&impliedFeatures, "android.hardware.telephony",
13402c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        String8("requested a telephony permission").string());
1341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.WRITE_EXTERNAL_STORAGE") {
1342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasWriteExternalStoragePermission = true;
1343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.READ_EXTERNAL_STORAGE") {
1344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasReadExternalStoragePermission = true;
1345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.READ_PHONE_STATE") {
1346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasReadPhoneStatePermission = true;
1347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.READ_CONTACTS") {
1348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasReadContactsPermission = true;
1349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.WRITE_CONTACTS") {
1350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasWriteContactsPermission = true;
1351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.READ_CALL_LOG") {
1352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasReadCallLogPermission = true;
1353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.WRITE_CALL_LOG") {
1354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasWriteCallLogPermission = true;
1355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
135658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski
135758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                            printUsesPermission(name,
1358ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    AaptXml::getIntegerAttribute(tree, REQUIRED_ATTR, 1) == 0,
1359ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    AaptXml::getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR));
136058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                       } else {
1361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    error.string());
1363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            goto bail;
1364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "uses-package") {
1366ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
1367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (name != "" && error == "") {
13682675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            printf("uses-package:'%s'\n",
13692675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                    ResTable::normalizeForOutput(name.string()).string());
1370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else {
1371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    error.string());
1373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                goto bail;
1374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "original-package") {
1376ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
1377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (name != "" && error == "") {
13782675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            printf("original-package:'%s'\n",
13792675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                    ResTable::normalizeForOutput(name.string()).string());
1380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else {
1381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    error.string());
1383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                goto bail;
1384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "supports-gl-texture") {
1386ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
1387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (name != "" && error == "") {
13882675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            printf("supports-gl-texture:'%s'\n",
13892675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                    ResTable::normalizeForOutput(name.string()).string());
1390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else {
1391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    error.string());
1393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                goto bail;
1394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "compatible-screens") {
13969cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                        printCompatibleScreens(tree, &error);
13979cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                        if (error != "") {
13989cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                            fprintf(stderr, "ERROR getting compatible screens: %s\n",
13999cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                                    error.string());
14009cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                            goto bail;
14019cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                        }
1402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        depth--;
1403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "package-verifier") {
1404ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
1405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (name != "" && error == "") {
1406ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            String8 publicKey = AaptXml::getAttribute(tree, PUBLIC_KEY_ATTR, &error);
1407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (publicKey != "" && error == "") {
1408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                printf("package-verifier: name='%s' publicKey='%s'\n",
14092675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                        ResTable::normalizeForOutput(name.string()).string(),
14102675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                        ResTable::normalizeForOutput(publicKey.string()).string());
1411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1414ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                } else if (depth == 3) {
1415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    withinActivity = false;
1416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    withinReceiver = false;
1417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    withinService = false;
14189d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                    withinProvider = false;
1419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasIntentFilter = false;
142094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    hasMetaHostPaymentCategory = false;
142194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    hasMetaOffHostPaymentCategory = false;
142294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    hasBindDeviceAdminPermission = false;
142394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    hasBindInputMethodPermission = false;
142494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    hasBindAccessibilityServicePermission = false;
142594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    hasBindPrintServicePermission = false;
142694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    hasBindNfcServicePermission = false;
14279d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                    hasRequiredSafAttributes = false;
14289d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                    hasBindNotificationListenerServicePermission = false;
1429eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock                    hasBindDreamServicePermission = false;
1430ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                    if (withinApplication) {
1431ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        if(tag == "activity") {
1432ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            withinActivity = true;
1433ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            activityName = AaptXml::getAttribute(tree, NAME_ATTR, &error);
1434ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (error != "") {
1435ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1436ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        error.string());
1437ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                goto bail;
1438ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
1439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1440ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            activityLabel = AaptXml::getResolvedAttribute(res, tree, LABEL_ATTR,
1441ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    &error);
1442ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (error != "") {
1443ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                fprintf(stderr, "ERROR getting 'android:label' attribute: %s\n",
1444ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        error.string());
1445ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                goto bail;
1446ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
1447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1448ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            activityIcon = AaptXml::getResolvedAttribute(res, tree, ICON_ATTR,
1449ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    &error);
1450ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (error != "") {
1451ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n",
1452ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        error.string());
1453ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                goto bail;
1454ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
1455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1456ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            activityBanner = AaptXml::getResolvedAttribute(res, tree, BANNER_ATTR,
1457ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    &error);
14580a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                            if (error != "") {
14590a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                fprintf(stderr, "ERROR getting 'android:banner' attribute: %s\n",
14600a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                        error.string());
14610a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                goto bail;
14620a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                            }
14630a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn
1464ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            int32_t orien = AaptXml::getResolvedIntegerAttribute(res, tree,
1465ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                    SCREEN_ORIENTATION_ATTR, &error);
1466ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (error == "") {
1467ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                if (orien == 0 || orien == 6 || orien == 8) {
1468ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                    // Requests landscape, sensorLandscape, or reverseLandscape.
14692c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                    addImpliedFeature(&impliedFeatures, "android.hardware.screen.landscape",
14702c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                            "one or more activities have specified a landscape orientation");
1471ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                } else if (orien == 1 || orien == 7 || orien == 9) {
1472ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                    // Requests portrait, sensorPortrait, or reversePortrait.
14732c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                    addImpliedFeature(&impliedFeatures, "android.hardware.screen.portrait",
14742c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                            "one or more activities have specified a portrait orientation");
1475ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                }
1476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1477ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        } else if (tag == "uses-library") {
1478ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            String8 libraryName = AaptXml::getAttribute(tree, NAME_ATTR, &error);
1479ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (error != "") {
1480ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                fprintf(stderr,
1481ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        "ERROR getting 'android:name' attribute for uses-library"
1482ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        " %s\n", error.string());
1483ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                goto bail;
1484ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
1485ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            int req = AaptXml::getIntegerAttribute(tree,
1486ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    REQUIRED_ATTR, 1);
1487ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            printf("uses-library%s:'%s'\n",
14882675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                    req ? "" : "-not-required", ResTable::normalizeForOutput(
14892675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                            libraryName.string()).string());
1490ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        } else if (tag == "receiver") {
1491ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            withinReceiver = true;
1492ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            receiverName = AaptXml::getAttribute(tree, NAME_ATTR, &error);
1493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1494ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (error != "") {
1495ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                fprintf(stderr,
1496ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        "ERROR getting 'android:name' attribute for receiver:"
1497ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        " %s\n", error.string());
1498ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                goto bail;
1499ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
1500a5018c900f126ee8424c82497f32983873db741bAdam Lesinski
1501ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            String8 permission = AaptXml::getAttribute(tree, PERMISSION_ATTR,
1502ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    &error);
1503a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            if (error == "") {
1504a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                if (permission == "android.permission.BIND_DEVICE_ADMIN") {
1505a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                    hasBindDeviceAdminPermission = true;
1506a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                }
1507a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            } else {
1508a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                fprintf(stderr, "ERROR getting 'android:permission' attribute for"
1509a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                        " receiver '%s': %s\n", receiverName.string(), error.string());
1510a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            }
1511ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        } else if (tag == "service") {
1512ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            withinService = true;
1513ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            serviceName = AaptXml::getAttribute(tree, NAME_ATTR, &error);
1514282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1515ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (error != "") {
1516ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                fprintf(stderr, "ERROR getting 'android:name' attribute for "
1517ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        "service:%s\n", error.string());
1518ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                goto bail;
1519ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
1520a5018c900f126ee8424c82497f32983873db741bAdam Lesinski
1521ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            String8 permission = AaptXml::getAttribute(tree, PERMISSION_ATTR,
1522ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    &error);
1523a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            if (error == "") {
1524a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                if (permission == "android.permission.BIND_INPUT_METHOD") {
1525a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                    hasBindInputMethodPermission = true;
1526a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                } else if (permission == "android.permission.BIND_ACCESSIBILITY_SERVICE") {
1527a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                    hasBindAccessibilityServicePermission = true;
1528a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                } else if (permission == "android.permission.BIND_PRINT_SERVICE") {
1529a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                    hasBindPrintServicePermission = true;
153094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                } else if (permission == "android.permission.BIND_NFC_SERVICE") {
153194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                    hasBindNfcServicePermission = true;
15329d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                } else if (permission == "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE") {
15339d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                    hasBindNotificationListenerServicePermission = true;
1534eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock                                } else if (permission == "android.permission.BIND_DREAM_SERVICE") {
1535eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock                                    hasBindDreamServicePermission = true;
1536a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                }
1537a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            } else {
1538a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                fprintf(stderr, "ERROR getting 'android:permission' attribute for"
1539a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                        " service '%s': %s\n", serviceName.string(), error.string());
1540a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            }
15419d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                        } else if (tag == "provider") {
15429d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            withinProvider = true;
15439d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski
1544ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            bool exported = AaptXml::getResolvedIntegerAttribute(res, tree,
1545ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    EXPORTED_ATTR, &error);
15469d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            if (error != "") {
15479d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                fprintf(stderr, "ERROR getting 'android:exported' attribute for provider:"
15489d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                        " %s\n", error.string());
15499d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                goto bail;
15509d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            }
15519d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski
1552ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            bool grantUriPermissions = AaptXml::getResolvedIntegerAttribute(
1553ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    res, tree, GRANT_URI_PERMISSIONS_ATTR, &error);
15549d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            if (error != "") {
15559d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                fprintf(stderr, "ERROR getting 'android:grantUriPermissions' attribute for provider:"
15569d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                        " %s\n", error.string());
15579d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                goto bail;
15589d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            }
15599d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski
1560ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            String8 permission = AaptXml::getResolvedAttribute(res, tree,
1561ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    PERMISSION_ATTR, &error);
15629d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            if (error != "") {
15639d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                fprintf(stderr, "ERROR getting 'android:permission' attribute for provider:"
15649d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                        " %s\n", error.string());
15659d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                goto bail;
15669d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            }
15679d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski
15689d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            hasRequiredSafAttributes |= exported && grantUriPermissions &&
15699d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                permission == "android.permission.MANAGE_DOCUMENTS";
15709d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski
1571ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        } else if (bundle->getIncludeMetaData() && tag == "meta-data") {
1572ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            String8 metaDataName = AaptXml::getResolvedAttribute(res, tree,
1573ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    NAME_ATTR, &error);
1574ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (error != "") {
1575ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                fprintf(stderr, "ERROR getting 'android:name' attribute for "
1576ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        "meta-data:%s\n", error.string());
1577ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                goto bail;
1578ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
15792675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            printf("meta-data: name='%s' ",
15802675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                    ResTable::normalizeForOutput(metaDataName.string()).string());
1581ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            printResolvedResourceAttribute(res, tree, VALUE_ATTR, String8("value"),
158276327314d2238e105f8b94909f9c0cf85caca318Maurice Chu                                    &error);
1583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (error != "") {
158476327314d2238e105f8b94909f9c0cf85caca318Maurice Chu                                // Try looking for a RESOURCE_ATTR
158576327314d2238e105f8b94909f9c0cf85caca318Maurice Chu                                error = "";
1586ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                printResolvedResourceAttribute(res, tree, RESOURCE_ATTR,
158776327314d2238e105f8b94909f9c0cf85caca318Maurice Chu                                        String8("resource"), &error);
1588ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                if (error != "") {
158976327314d2238e105f8b94909f9c0cf85caca318Maurice Chu                                    fprintf(stderr, "ERROR getting 'android:value' or "
159076327314d2238e105f8b94909f9c0cf85caca318Maurice Chu                                            "'android:resource' attribute for "
159176327314d2238e105f8b94909f9c0cf85caca318Maurice Chu                                            "meta-data:%s\n", error.string());
1592ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                    goto bail;
1593ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                }
1594ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
159576327314d2238e105f8b94909f9c0cf85caca318Maurice Chu                            printf("\n");
1596ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        } else if (withinSupportsInput && tag == "input-type") {
1597ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
1598ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (name != "" && error == "") {
1599ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                supportedInput.add(name);
1600ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            } else {
1601ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1602ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        error.string());
1603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                goto bail;
1604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
16062c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                    } else if (withinFeatureGroup && tag == "uses-feature") {
1607d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                        FeatureGroup& top = featureGroups.editTop();
1608d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski
1609ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        String8 name = AaptXml::getResolvedAttribute(res, tree, NAME_ATTR, &error);
1610d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                        if (name != "" && error == "") {
1611d3edfde51bd069a63e820282421d1a534fcf00ceAdam Lesinski                            top.features.add(name, true);
1612d3edfde51bd069a63e820282421d1a534fcf00ceAdam Lesinski                            addParentFeatures(&top, name);
1613d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                        } else {
1614ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            int vers = AaptXml::getIntegerAttribute(tree, GL_ES_VERSION_ATTR,
1615ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    &error);
1616d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                            if (error == "") {
1617d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                                if (vers > top.openGLESVersion) {
1618d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                                    top.openGLESVersion = vers;
1619d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                                }
1620d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                            }
16212c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                        }
1622a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                    }
162394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                } else if (depth == 4) {
162494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    if (tag == "intent-filter") {
162594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        hasIntentFilter = true;
162694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        withinIntentFilter = true;
162794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actMainActivity = false;
162894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actWidgetReceivers = false;
162994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actImeService = false;
163094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actWallpaperService = false;
163194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actAccessibilityService = false;
163294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actPrintService = false;
163394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actDeviceAdminEnabled = false;
163494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actHostApduService = false;
163594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actOffHostApduService = false;
16369d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                        actDocumentsProvider = false;
16379d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                        actNotificationListenerService = false;
1638eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock                        actDreamService = false;
16399d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                        actCamera = false;
16409d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                        actCameraSecure = false;
16419d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                        catLauncher = false;
164294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    } else if (withinService && tag == "meta-data") {
1643ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
164494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        if (error != "") {
164594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            fprintf(stderr, "ERROR getting 'android:name' attribute for"
164694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                    " meta-data tag in service '%s': %s\n", serviceName.string(), error.string());
164794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            goto bail;
164894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        }
164994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
165094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        if (name == "android.nfc.cardemulation.host_apdu_service" ||
165194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                name == "android.nfc.cardemulation.off_host_apdu_service") {
165294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            bool offHost = true;
165394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            if (name == "android.nfc.cardemulation.host_apdu_service") {
165494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                offHost = false;
165594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            }
165694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
1657ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            String8 xmlPath = AaptXml::getResolvedAttribute(res, tree,
1658ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    RESOURCE_ATTR, &error);
165994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            if (error != "") {
166094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                fprintf(stderr, "ERROR getting 'android:resource' attribute for"
166194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                        " meta-data tag in service '%s': %s\n", serviceName.string(), error.string());
166294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                goto bail;
166394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            }
166494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
166594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            Vector<String8> categories = getNfcAidCategories(assets, xmlPath,
166694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                    offHost, &error);
166794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            if (error != "") {
166894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                fprintf(stderr, "ERROR getting AID category for service '%s'\n",
166994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                        serviceName.string());
167094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                goto bail;
167194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            }
167294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
167394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            const size_t catLen = categories.size();
167494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            for (size_t i = 0; i < catLen; i++) {
167594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                bool paymentCategory = (categories[i] == "payment");
167694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                if (offHost) {
167794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                    hasMetaOffHostPaymentCategory |= paymentCategory;
167894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                } else {
167994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                    hasMetaHostPaymentCategory |= paymentCategory;
168094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                }
168194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            }
168294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        }
168394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    }
1684a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                } else if ((depth == 5) && withinIntentFilter) {
1685a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                    String8 action;
1686a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                    if (tag == "action") {
1687ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        action = AaptXml::getAttribute(tree, NAME_ATTR, &error);
1688a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        if (error != "") {
1689a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1690a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                    error.string());
1691a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            goto bail;
1692a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        }
1693a5018c900f126ee8424c82497f32983873db741bAdam Lesinski
1694a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        if (withinActivity) {
1695a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            if (action == "android.intent.action.MAIN") {
1696a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                isMainActivity = true;
1697a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                actMainActivity = true;
16989d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            } else if (action == "android.media.action.STILL_IMAGE_CAMERA" ||
16999d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                    action == "android.media.action.VIDEO_CAMERA") {
17009d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                actCamera = true;
17019d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            } else if (action == "android.media.action.STILL_IMAGE_CAMERA_SECURE") {
17029d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                actCameraSecure = true;
1703282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1704a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        } else if (withinReceiver) {
1705a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            if (action == "android.appwidget.action.APPWIDGET_UPDATE") {
1706a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                actWidgetReceivers = true;
1707a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            } else if (action == "android.app.action.DEVICE_ADMIN_ENABLED") {
1708a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                actDeviceAdminEnabled = true;
1709282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1710a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        } else if (withinService) {
1711a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            if (action == "android.view.InputMethod") {
1712a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                actImeService = true;
1713a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            } else if (action == "android.service.wallpaper.WallpaperService") {
1714a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                actWallpaperService = true;
1715a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            } else if (action == "android.accessibilityservice.AccessibilityService") {
1716a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                actAccessibilityService = true;
1717a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            } else if (action == "android.printservice.PrintService") {
1718a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                actPrintService = true;
171994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            } else if (action == "android.nfc.cardemulation.action.HOST_APDU_SERVICE") {
172094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                actHostApduService = true;
172194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            } else if (action == "android.nfc.cardemulation.action.OFF_HOST_APDU_SERVICE") {
172294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                actOffHostApduService = true;
17239d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            } else if (action == "android.service.notification.NotificationListenerService") {
17249d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                actNotificationListenerService = true;
1725eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock                            } else if (action == "android.service.dreams.DreamService") {
1726eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock                                actDreamService = true;
17279d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            }
17289d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                        } else if (withinProvider) {
17299d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            if (action == "android.content.action.DOCUMENTS_PROVIDER") {
17309d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                actDocumentsProvider = true;
1731282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1732282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1733a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        if (action == "android.intent.action.SEARCH") {
1734a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            isSearchable = true;
1735a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        }
1736a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                    }
1737282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1738a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                    if (tag == "category") {
1739ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        String8 category = AaptXml::getAttribute(tree, NAME_ATTR, &error);
1740a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        if (error != "") {
1741a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            fprintf(stderr, "ERROR getting 'name' attribute: %s\n",
1742a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                    error.string());
1743a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            goto bail;
1744a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        }
1745a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        if (withinActivity) {
1746a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            if (category == "android.intent.category.LAUNCHER") {
1747a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                isLauncherActivity = true;
17480a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                            } else if (category == "android.intent.category.LEANBACK_LAUNCHER") {
17490a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                isLeanbackLauncherActivity = true;
17509d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            } else if (category == "android.intent.category.HOME") {
17519d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                catLauncher = true;
1752282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1753282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1754282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1755282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1756282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1757282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1758282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Pre-1.6 implicitly granted permission compatibility logic
1759282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (targetSdk < 4) {
1760282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!hasWriteExternalStoragePermission) {
176158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesPermission(String8("android.permission.WRITE_EXTERNAL_STORAGE"));
176258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesImpliedPermission(String8("android.permission.WRITE_EXTERNAL_STORAGE"),
176358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                            String8("targetSdkVersion < 4"));
1764282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasWriteExternalStoragePermission = true;
1765282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1766282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!hasReadPhoneStatePermission) {
176758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesPermission(String8("android.permission.READ_PHONE_STATE"));
176858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesImpliedPermission(String8("android.permission.READ_PHONE_STATE"),
176958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                            String8("targetSdkVersion < 4"));
1770282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1771282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // If the application has requested WRITE_EXTERNAL_STORAGE, we will
1774282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // force them to always take READ_EXTERNAL_STORAGE as well.  We always
1775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // do this (regardless of target API version) because we can't have
1776282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // an app with write permission but not read permission.
1777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!hasReadExternalStoragePermission && hasWriteExternalStoragePermission) {
177858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                printUsesPermission(String8("android.permission.READ_EXTERNAL_STORAGE"));
177958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                printUsesImpliedPermission(String8("android.permission.READ_EXTERNAL_STORAGE"),
178058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                        String8("requested WRITE_EXTERNAL_STORAGE"));
1781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1782282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Pre-JellyBean call log permission compatibility.
1784282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (targetSdk < 16) {
1785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!hasReadCallLogPermission && hasReadContactsPermission) {
178658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesPermission(String8("android.permission.READ_CALL_LOG"));
178758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesImpliedPermission(String8("android.permission.READ_CALL_LOG"),
178858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                            String8("targetSdkVersion < 16 and requested READ_CONTACTS"));
1789282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1790282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!hasWriteCallLogPermission && hasWriteContactsPermission) {
179158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesPermission(String8("android.permission.WRITE_CALL_LOG"));
179258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesImpliedPermission(String8("android.permission.WRITE_CALL_LOG"),
179358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                            String8("targetSdkVersion < 16 and requested WRITE_CONTACTS"));
1794282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1795282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1796282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
17972c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski            addImpliedFeature(&impliedFeatures, "android.hardware.touchscreen",
17982c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                    "default feature for all apps");
17992c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
18002c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski            const size_t numFeatureGroups = featureGroups.size();
18012c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski            if (numFeatureGroups == 0) {
18022c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                // If no <feature-group> tags were defined, apply auto-implied features.
18032c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                printFeatureGroup(commonFeatures, &impliedFeatures);
18042c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
18052c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski            } else {
18062c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                // <feature-group> tags are defined, so we ignore implied features and
18072c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                for (size_t i = 0; i < numFeatureGroups; i++) {
18082c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                    FeatureGroup& grp = featureGroups.editItemAt(i);
18092c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
1810d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                    if (commonFeatures.openGLESVersion > grp.openGLESVersion) {
1811d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                        grp.openGLESVersion = commonFeatures.openGLESVersion;
1812d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                    }
1813d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski
18142c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                    // Merge the features defined in the top level (not inside a <feature-group>)
18152c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                    // with this feature group.
18162c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                    const size_t numCommonFeatures = commonFeatures.features.size();
18172c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                    for (size_t j = 0; j < numCommonFeatures; j++) {
18182c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                        if (grp.features.indexOfKey(commonFeatures.features.keyAt(j)) < 0) {
1819d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                            grp.features.add(commonFeatures.features.keyAt(j),
1820d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                                    commonFeatures.features[j]);
18212c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                        }
1822282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1823282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
18242c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                   if (!grp.features.isEmpty()) {
18252c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                        printFeatureGroup(grp);
18262c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                    }
1827282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1828282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1829282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
18302c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
1831282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (hasWidgetReceivers) {
18329d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("app-widget");
1833282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1834a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            if (hasDeviceAdminReceiver) {
18359d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("device-admin");
1836a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            }
1837282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (hasImeService) {
18389d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("ime");
1839282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1840282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (hasWallpaperService) {
18419d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("wallpaper");
1842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1843a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            if (hasAccessibilityService) {
18449d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("accessibility");
1845a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            }
1846a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            if (hasPrintService) {
18479d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("print-service");
1848a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            }
184994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            if (hasPaymentService) {
18509d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("payment");
18519d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            }
18529d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            if (isSearchable) {
18539d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("search");
18549d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            }
18559d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            if (hasDocumentsProvider) {
18569d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("document-provider");
18579d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            }
18589d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            if (hasLauncher) {
18599d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("launcher");
18609d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            }
18619d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            if (hasNotificationListenerService) {
18629d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("notification-listener");
18639d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            }
1864eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock            if (hasDreamService) {
1865eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock                printComponentPresence("dream");
1866eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock            }
18679d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            if (hasCameraActivity) {
18689d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("camera");
18699d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            }
18709d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            if (hasCameraSecureActivity) {
18719d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("camera-secure");
18729d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            }
18739d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski
18749d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            if (hasMainActivity) {
18759d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printf("main\n");
187694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            }
1877282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (hasOtherActivities) {
1878282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("other-activities\n");
1879282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
18809d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski             if (hasOtherReceivers) {
1881282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("other-receivers\n");
1882282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1883282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (hasOtherServices) {
1884282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("other-services\n");
1885282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1886282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1887282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // For modern apps, if screen size buckets haven't been specified
1888282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // but the new width ranges have, then infer the buckets from them.
1889282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (smallScreen > 0 && normalScreen > 0 && largeScreen > 0 && xlargeScreen > 0
1890282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    && requiresSmallestWidthDp > 0) {
1891282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                int compatWidth = compatibleWidthLimitDp;
1892282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (compatWidth <= 0) {
1893282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    compatWidth = requiresSmallestWidthDp;
1894282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1895282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (requiresSmallestWidthDp <= 240 && compatWidth >= 240) {
1896282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    smallScreen = -1;
1897282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1898282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    smallScreen = 0;
1899282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1900282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (requiresSmallestWidthDp <= 320 && compatWidth >= 320) {
1901282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    normalScreen = -1;
1902282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1903282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    normalScreen = 0;
1904282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1905282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (requiresSmallestWidthDp <= 480 && compatWidth >= 480) {
1906282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    largeScreen = -1;
1907282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1908282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    largeScreen = 0;
1909282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1910282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (requiresSmallestWidthDp <= 720 && compatWidth >= 720) {
1911282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    xlargeScreen = -1;
1912282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1913282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    xlargeScreen = 0;
1914282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1915282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1916282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1917282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Determine default values for any unspecified screen sizes,
1918282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // based on the target SDK of the package.  As of 4 (donut)
1919282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // the screen size support was introduced, so all default to
1920282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // enabled.
1921282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (smallScreen > 0) {
1922282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                smallScreen = targetSdk >= 4 ? -1 : 0;
1923282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1924282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (normalScreen > 0) {
1925282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                normalScreen = -1;
1926282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1927282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (largeScreen > 0) {
1928282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                largeScreen = targetSdk >= 4 ? -1 : 0;
1929282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1930282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (xlargeScreen > 0) {
1931282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Introduced in Gingerbread.
1932282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                xlargeScreen = targetSdk >= 9 ? -1 : 0;
1933282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1934282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (anyDensity > 0) {
1935282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                anyDensity = (targetSdk >= 4 || requiresSmallestWidthDp > 0
1936282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        || compatibleWidthLimitDp > 0) ? -1 : 0;
1937282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1938282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("supports-screens:");
1939282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (smallScreen != 0) {
1940282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf(" 'small'");
1941282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1942282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (normalScreen != 0) {
1943282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf(" 'normal'");
1944282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1945282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (largeScreen != 0) {
1946282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf(" 'large'");
1947282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1948282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (xlargeScreen != 0) {
1949282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf(" 'xlarge'");
1950282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1951282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("\n");
1952282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("supports-any-density: '%s'\n", anyDensity ? "true" : "false");
1953282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (requiresSmallestWidthDp > 0) {
1954282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("requires-smallest-width:'%d'\n", requiresSmallestWidthDp);
1955282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1956282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (compatibleWidthLimitDp > 0) {
1957282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("compatible-width-limit:'%d'\n", compatibleWidthLimitDp);
1958282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1959282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (largestWidthLimitDp > 0) {
1960282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("largest-width-limit:'%d'\n", largestWidthLimitDp);
1961282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1962282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1963282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("locales:");
1964282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t NL = locales.size();
1965282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t i=0; i<NL; i++) {
1966282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                const char* localeStr =  locales[i].string();
1967282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (localeStr == NULL || strlen(localeStr) == 0) {
1968282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    localeStr = "--_--";
1969282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1970282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf(" '%s'", localeStr);
1971282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1972282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("\n");
1973282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1974282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("densities:");
1975282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t ND = densities.size();
1976282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t i=0; i<ND; i++) {
1977282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf(" '%d'", densities[i]);
1978282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1979282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("\n");
1980282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1981282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            AssetDir* dir = assets.openNonAssetDir(assetsCookie, "lib");
1982282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (dir != NULL) {
1983282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (dir->getFileCount() > 0) {
1984e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                    SortedVector<String8> architectures;
1985282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    for (size_t i=0; i<dir->getFileCount(); i++) {
1986e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        architectures.add(ResTable::normalizeForOutput(
1987e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                                dir->getFileName(i).string()));
1988e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                    }
1989e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski
1990e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                    bool outputAltNativeCode = false;
1991e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                    // A multiArch package is one that contains 64-bit and
1992e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                    // 32-bit versions of native code and expects 3rd-party
1993e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                    // apps to load these native code libraries. Since most
1994e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                    // 64-bit systems also support 32-bit apps, the apps
1995e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                    // loading this multiArch package's code may be either
1996e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                    // 32-bit or 64-bit.
1997e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                    if (hasMultiArch) {
1998e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        // If this is a multiArch package, report the 64-bit
1999e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        // version only. Then as a separate entry, report the
2000e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        // rest.
2001e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        //
2002e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        // If we report the 32-bit architecture, this APK will
2003e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        // be installed on a 32-bit device, causing a large waste
2004e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        // of bandwidth and disk space. This assumes that
2005e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        // the developer of the multiArch package has also
2006e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        // made a version that is 32-bit only.
2007e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        String8 intel64("x86_64");
2008e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        String8 arm64("arm64-v8a");
2009e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        ssize_t index = architectures.indexOf(intel64);
2010e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        if (index < 0) {
2011e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                            index = architectures.indexOf(arm64);
2012e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        }
2013e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski
2014e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        if (index >= 0) {
2015e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                            printf("native-code: '%s'\n", architectures[index].string());
2016e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                            architectures.removeAt(index);
2017e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                            outputAltNativeCode = true;
2018e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        }
2019e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                    }
2020e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski
2021e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                    const size_t archCount = architectures.size();
2022e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                    if (archCount > 0) {
2023e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        if (outputAltNativeCode) {
2024e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                            printf("alt-");
2025e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        }
2026e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        printf("native-code:");
2027e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        for (size_t i = 0; i < archCount; i++) {
2028e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                            printf(" '%s'", architectures[i].string());
2029e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        }
2030e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        printf("\n");
2031282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2032282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2033282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                delete dir;
2034282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2035282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else if (strcmp("badger", option) == 0) {
2036282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("%s", CONSOLE_DATA);
2037282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else if (strcmp("configurations", option) == 0) {
2038282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Vector<ResTable_config> configs;
2039282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            res.getConfigurations(&configs);
2040282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t N = configs.size();
2041282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t i=0; i<N; i++) {
2042282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("%s\n", configs[i].toString().string());
2043282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2044282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
2045282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: unknown dump option '%s'\n", option);
2046282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
2047282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2048282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2049282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2050282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    result = NO_ERROR;
2051282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2052282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail:
2053282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (asset) {
2054282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        delete asset;
2055282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2056282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return (result != NO_ERROR);
2057282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2058282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2059282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2060282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
2061282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Handle the "add" command, which wants to add files to a new or
2062282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * pre-existing archive.
2063282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
2064282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doAdd(Bundle* bundle)
2065282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2066282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ZipFile* zip = NULL;
2067282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t result = UNKNOWN_ERROR;
2068282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char* zipFileName;
2069282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2070282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getUpdate()) {
2071282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        /* avoid confusion */
2072282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: can't use '-u' with add\n");
2073282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2074282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2075282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2076282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getFileSpecCount() < 1) {
2077282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: must specify zip file name\n");
2078282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2079282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2080282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    zipFileName = bundle->getFileSpecEntry(0);
2081282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2082282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getFileSpecCount() < 2) {
2083282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "NOTE: nothing to do\n");
2084282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2085282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2086282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2087282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    zip = openReadWrite(zipFileName, true);
2088282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (zip == NULL) {
2089282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: failed opening/creating '%s' as Zip file\n", zipFileName);
2090282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2091282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2092282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2093282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (int i = 1; i < bundle->getFileSpecCount(); i++) {
2094282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const char* fileName = bundle->getFileSpecEntry(i);
2095282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2096282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (strcasecmp(String8(fileName).getPathExtension().string(), ".gz") == 0) {
2097282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf(" '%s'... (from gzip)\n", fileName);
2098282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            result = zip->addGzip(fileName, String8(fileName).getBasePath().string(), NULL);
2099282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
2100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (bundle->getJunkPath()) {
2101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String8 storageName = String8(fileName).getPathLeaf();
21022675f769673f69b0661ddee346292f25cb30a296Maurice Chu                printf(" '%s' as '%s'...\n", fileName,
21032675f769673f69b0661ddee346292f25cb30a296Maurice Chu                        ResTable::normalizeForOutput(storageName.string()).string());
2104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                result = zip->add(fileName, storageName.string(),
2105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  bundle->getCompressionMethod(), NULL);
2106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
2107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf(" '%s'...\n", fileName);
2108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                result = zip->add(fileName, bundle->getCompressionMethod(), NULL);
2109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (result != NO_ERROR) {
2112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "Unable to add '%s' to '%s'", bundle->getFileSpecEntry(i), zipFileName);
2113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (result == NAME_NOT_FOUND) {
2114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, ": file not found\n");
2115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (result == ALREADY_EXISTS) {
2116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, ": already exists in archive\n");
2117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
2118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, "\n");
2119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
2121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    result = NO_ERROR;
2125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail:
2127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    delete zip;
2128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return (result != NO_ERROR);
2129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
2133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Delete files from an existing archive.
2134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
2135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doRemove(Bundle* bundle)
2136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ZipFile* zip = NULL;
2138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t result = UNKNOWN_ERROR;
2139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char* zipFileName;
2140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getFileSpecCount() < 1) {
2142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: must specify zip file name\n");
2143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    zipFileName = bundle->getFileSpecEntry(0);
2146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getFileSpecCount() < 2) {
2148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "NOTE: nothing to do\n");
2149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    zip = openReadWrite(zipFileName, false);
2153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (zip == NULL) {
2154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: failed opening Zip archive '%s'\n",
2155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            zipFileName);
2156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (int i = 1; i < bundle->getFileSpecCount(); i++) {
2160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const char* fileName = bundle->getFileSpecEntry(i);
2161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ZipEntry* entry;
2162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        entry = zip->getEntryByName(fileName);
2164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (entry == NULL) {
2165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf(" '%s' NOT FOUND\n", fileName);
2166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
2167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        result = zip->remove(entry);
2170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (result != NO_ERROR) {
2172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "Unable to delete '%s' from '%s'\n",
2173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                bundle->getFileSpecEntry(i), zipFileName);
2174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
2175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /* update the archive */
2179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    zip->flush();
2180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail:
2182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    delete zip;
2183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return (result != NO_ERROR);
2184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
21863921e87e6e67a063caa1987937d7944b24aef489Adam Lesinskistatic status_t addResourcesToBuilder(const sp<AaptDir>& dir, const sp<ApkBuilder>& builder, bool ignoreConfig=false) {
2187fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    const size_t numDirs = dir->getDirs().size();
2188fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    for (size_t i = 0; i < numDirs; i++) {
21893921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski        bool ignore = ignoreConfig;
21903921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski        const sp<AaptDir>& subDir = dir->getDirs().valueAt(i);
21913921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski        const char* dirStr = subDir->getLeaf().string();
21923921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski        if (!ignore && strstr(dirStr, "mipmap") == dirStr) {
21933921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski            ignore = true;
21943921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski        }
21953921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski        status_t err = addResourcesToBuilder(subDir, builder, ignore);
2196fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        if (err != NO_ERROR) {
2197fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            return err;
2198fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        }
2199fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    }
2200fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski
2201fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    const size_t numFiles = dir->getFiles().size();
2202fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    for (size_t i = 0; i < numFiles; i++) {
2203fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        sp<AaptGroup> gp = dir->getFiles().valueAt(i);
2204fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        const size_t numConfigs = gp->getFiles().size();
2205fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        for (size_t j = 0; j < numConfigs; j++) {
22063921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski            status_t err = NO_ERROR;
22073921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski            if (ignoreConfig) {
22083921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski                err = builder->getBaseSplit()->addEntry(gp->getPath(), gp->getFiles().valueAt(j));
22093921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski            } else {
22103921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski                err = builder->addEntry(gp->getPath(), gp->getFiles().valueAt(j));
22113921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski            }
2212fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            if (err != NO_ERROR) {
2213fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                fprintf(stderr, "Failed to add %s (%s) to builder.\n",
2214fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                        gp->getPath().string(), gp->getFiles()[j]->getPrintableSource().string());
2215fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                return err;
2216fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            }
2217fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        }
2218fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    }
2219fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    return NO_ERROR;
2220fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski}
2221fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski
2222fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinskistatic String8 buildApkName(const String8& original, const sp<ApkSplit>& split) {
2223fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (split->isBase()) {
2224fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        return original;
2225fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    }
2226fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski
2227fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    String8 ext(original.getPathExtension());
2228fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (ext == String8(".apk")) {
2229fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        return String8::format("%s_%s%s",
2230fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                original.getBasePath().string(),
2231fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                split->getDirectorySafeName().string(),
2232fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                ext.string());
2233fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    }
2234fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski
2235fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    return String8::format("%s_%s", original.string(),
2236fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            split->getDirectorySafeName().string());
2237fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski}
2238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
2240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Package up an asset directory and associated application files.
2241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
2242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doPackage(Bundle* bundle)
2243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char* outputAPKFile;
2245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int retVal = 1;
2246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err;
2247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<AaptAssets> assets;
2248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int N;
2249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    FILE* fp;
2250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String8 dependencyFile;
2251fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    sp<ApkBuilder> builder;
2252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2253a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin    // -c en_XA or/and ar_XB means do pseudolocalization
2254fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    sp<WeakResourceFilter> configFilter = new WeakResourceFilter();
2255fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    err = configFilter->parse(bundle->getConfigurations());
2256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
2257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2259fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (configFilter->containsPseudo()) {
2260a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        bundle->setPseudolocalize(bundle->getPseudolocalize() | PSEUDO_ACCENTED);
2261a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin    }
2262fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (configFilter->containsPseudoBidi()) {
2263a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        bundle->setPseudolocalize(bundle->getPseudolocalize() | PSEUDO_BIDI);
2264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    N = bundle->getFileSpecCount();
2267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (N < 1 && bundle->getResourceSourceDirs().size() == 0 && bundle->getJarFiles().size() == 0
226809384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski            && bundle->getAndroidManifestFile() == NULL && bundle->getAssetSourceDirs().size() == 0) {
2269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: no input files\n");
2270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    outputAPKFile = bundle->getOutputAPKFile();
2274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Make sure the filenames provided exist and are of the appropriate type.
2276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (outputAPKFile) {
2277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        FileType type;
2278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        type = getFileType(outputAPKFile);
2279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (type != kFileTypeNonexistent && type != kFileTypeRegular) {
2280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr,
2281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                "ERROR: output file '%s' exists but is not regular file\n",
2282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                outputAPKFile);
2283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
2284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Load the assets.
2288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    assets = new AaptAssets();
2289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Set up the resource gathering in assets if we're going to generate
2291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // dependency files. Every time we encounter a resource while slurping
2292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // the tree, we'll add it to these stores so we have full resource paths
2293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // to write to a dependency file.
2294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getGenDependencies()) {
2295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<FilePathStore> resPathStore = new FilePathStore;
2296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        assets->setFullResPaths(resPathStore);
2297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<FilePathStore> assetPathStore = new FilePathStore;
2298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        assets->setFullAssetPaths(assetPathStore);
2299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    err = assets->slurpFromArgs(bundle);
2302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err < 0) {
2303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getVerbose()) {
2307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        assets->print(String8());
2308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2310fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    // Create the ApkBuilder, which will collect the compiled files
2311fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    // to write to the final APK (or sets of APKs if we are building
2312fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    // a Split APK.
2313fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    builder = new ApkBuilder(configFilter);
2314fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski
2315fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    // If we are generating a Split APK, find out which configurations to split on.
2316fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (bundle->getSplitConfigurations().size() > 0) {
2317fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        const Vector<String8>& splitStrs = bundle->getSplitConfigurations();
2318fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        const size_t numSplits = splitStrs.size();
2319fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        for (size_t i = 0; i < numSplits; i++) {
2320fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            std::set<ConfigDescription> configs;
2321fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            if (!AaptConfig::parseCommaSeparatedList(splitStrs[i], &configs)) {
2322fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                fprintf(stderr, "ERROR: failed to parse split configuration '%s'\n", splitStrs[i].string());
2323fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                goto bail;
2324fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            }
2325fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski
2326fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            err = builder->createSplitForConfigs(configs);
2327fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            if (err != NO_ERROR) {
2328fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                goto bail;
2329fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            }
2330fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        }
2331fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    }
2332fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski
2333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // If they asked for any fileAs that need to be compiled, do so.
2334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getResourceSourceDirs().size() || bundle->getAndroidManifestFile()) {
2335fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        err = buildResources(bundle, assets, builder);
2336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != 0) {
2337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
2338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // At this point we've read everything and processed everything.  From here
2342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // on out it's just writing output files.
2343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (SourcePos::hasErrors()) {
2344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Update symbols with information about which ones are needed as Java symbols.
2348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    assets->applyJavaSymbols();
2349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (SourcePos::hasErrors()) {
2350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // If we've been asked to generate a dependency file, do that here
2354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getGenDependencies()) {
2355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // If this is the packaging step, generate the dependency file next to
2356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // the output apk (e.g. bin/resources.ap_.d)
2357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (outputAPKFile) {
2358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            dependencyFile = String8(outputAPKFile);
2359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Add the .d extension to the dependency file.
2360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            dependencyFile.append(".d");
2361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
2362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Else if this is the R.java dependency generation step,
2363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // generate the dependency file in the R.java package subdirectory
2364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // e.g. gen/com/foo/app/R.java.d
2365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            dependencyFile = String8(bundle->getRClassDir());
2366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            dependencyFile.appendPath("R.java.d");
2367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Make sure we have a clean dependency file to start with
2369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fp = fopen(dependencyFile, "w");
2370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fclose(fp);
2371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Write out R.java constants
2374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (!assets->havePrivateSymbols()) {
2375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (bundle->getCustomPackage() == NULL) {
2376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Write the R.java file into the appropriate class directory
2377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // e.g. gen/com/foo/app/R.java
23781e466385d4a4f1acee080fa0fdf16cc8fd8ce7caAdam Lesinski            err = writeResourceSymbols(bundle, assets, assets->getPackage(), true,
23791e466385d4a4f1acee080fa0fdf16cc8fd8ce7caAdam Lesinski                    bundle->getBuildSharedLibrary());
2380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
2381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const String8 customPkg(bundle->getCustomPackage());
23821e466385d4a4f1acee080fa0fdf16cc8fd8ce7caAdam Lesinski            err = writeResourceSymbols(bundle, assets, customPkg, true,
23831e466385d4a4f1acee080fa0fdf16cc8fd8ce7caAdam Lesinski                    bundle->getBuildSharedLibrary());
2384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err < 0) {
2386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
2387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // If we have library files, we're going to write our R.java file into
2389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // the appropriate class directory for those libraries as well.
2390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // e.g. gen/com/foo/app/lib/R.java
2391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (bundle->getExtraPackages() != NULL) {
2392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Split on colon
2393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 libs(bundle->getExtraPackages());
2394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            char* packageString = strtok(libs.lockBuffer(libs.length()), ":");
2395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            while (packageString != NULL) {
2396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Write the R.java file out with the correct package name
23970f3a5a6559a955ea20f1ae2d3e0995f3fa821c90Marcin Kosiba                err = writeResourceSymbols(bundle, assets, String8(packageString), true,
23980f3a5a6559a955ea20f1ae2d3e0995f3fa821c90Marcin Kosiba                        bundle->getBuildSharedLibrary());
2399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (err < 0) {
2400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    goto bail;
2401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                packageString = strtok(NULL, ":");
2403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            libs.unlockBuffer();
2405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
24071e466385d4a4f1acee080fa0fdf16cc8fd8ce7caAdam Lesinski        err = writeResourceSymbols(bundle, assets, assets->getPackage(), false, false);
2408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err < 0) {
2409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
2410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
24111e466385d4a4f1acee080fa0fdf16cc8fd8ce7caAdam Lesinski        err = writeResourceSymbols(bundle, assets, assets->getSymbolsPrivatePackage(), true, false);
2412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err < 0) {
2413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
2414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Write out the ProGuard file
2418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    err = writeProguardFile(bundle, assets);
2419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err < 0) {
2420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Write the apk
2424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (outputAPKFile) {
2425fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        // Gather all resources and add them to the APK Builder. The builder will then
2426fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        // figure out which Split they belong in.
2427fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        err = addResourcesToBuilder(assets, builder);
2428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != NO_ERROR) {
2429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
2430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2431fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski
2432fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        const Vector<sp<ApkSplit> >& splits = builder->getSplits();
2433fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        const size_t numSplits = splits.size();
2434fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        for (size_t i = 0; i < numSplits; i++) {
2435fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            const sp<ApkSplit>& split = splits[i];
2436fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            String8 outputPath = buildApkName(String8(outputAPKFile), split);
2437fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            err = writeAPK(bundle, outputPath, split);
2438fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            if (err != NO_ERROR) {
2439fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                fprintf(stderr, "ERROR: packaging of '%s' failed\n", outputPath.string());
2440fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                goto bail;
2441fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            }
2442fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        }
2443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2444282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2445282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // If we've been asked to generate a dependency file, we need to finish up here.
2446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // the writeResourceSymbols and writeAPK functions have already written the target
2447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // half of the dependency file, now we need to write the prerequisites. (files that
2448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // the R.java file or .ap_ file depend on)
2449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getGenDependencies()) {
2450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Now that writeResourceSymbols or writeAPK has taken care of writing
2451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // the targets to our dependency file, we'll write the prereqs
2452282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fp = fopen(dependencyFile, "a+");
2453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(fp, " : ");
2454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        bool includeRaw = (outputAPKFile != NULL);
2455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        err = writeDependencyPreReqs(bundle, assets, fp, includeRaw);
2456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Also manually add the AndroidManifeset since it's not under res/ or assets/
2457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // and therefore was not added to our pathstores during slurping
2458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(fp, "%s \\\n", bundle->getAndroidManifestFile());
2459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fclose(fp);
2460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    retVal = 0;
2463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail:
2464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (SourcePos::hasErrors()) {
2465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        SourcePos::printErrors(stderr);
2466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return retVal;
2468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
2471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Do PNG Crunching
2472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * PRECONDITIONS
2473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *  -S flag points to a source directory containing drawable* folders
2474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *  -C flag points to destination directory. The folder structure in the
2475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *     source directory will be mirrored to the destination (cache) directory
2476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
2477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * POSTCONDITIONS
2478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *  Destination directory will be updated to match the PNG files in
24792675f769673f69b0661ddee346292f25cb30a296Maurice Chu *  the source directory.
2480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
2481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doCrunch(Bundle* bundle)
2482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(stdout, "Crunching PNG Files in ");
2484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(stdout, "source dir: %s\n", bundle->getResourceSourceDirs()[0]);
2485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(stdout, "To destination dir: %s\n", bundle->getCrunchedOutputDir());
2486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    updatePreProcessedCache(bundle);
2488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
2490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
2493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Do PNG Crunching on a single flag
2494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *  -i points to a single png file
2495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *  -o points to a single png output file
2496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
2497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doSingleCrunch(Bundle* bundle)
2498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(stdout, "Crunching single PNG file: %s\n", bundle->getSingleCrunchInputFile());
2500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(stdout, "\tOutput file: %s\n", bundle->getSingleCrunchOutputFile());
2501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String8 input(bundle->getSingleCrunchInputFile());
2503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String8 output(bundle->getSingleCrunchOutputFile());
2504282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (preProcessImageToCache(bundle, input, output) != NO_ERROR) {
2506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // we can't return the status_t as it gets truncate to the lower 8 bits.
2507282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return 42;
2508282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2509282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
2511282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2512282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
25136f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochezint runInDaemonMode(Bundle* bundle) {
25146f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez    std::cout << "Ready" << std::endl;
25156f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez    for (std::string line; std::getline(std::cin, line);) {
25166f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez        if (line == "quit") {
25176f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez            return NO_ERROR;
25186f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez        }
25196f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez        std::stringstream ss;
25206f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez        ss << line;
25216f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez        std::string s;
25226f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez
25236f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez        std::string command, parameterOne, parameterTwo;
25246f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez        std::getline(ss, command, ' ');
25256f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez        std::getline(ss, parameterOne, ' ');
25266f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez        std::getline(ss, parameterTwo, ' ');
25276f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez        if (command[0] == 's') {
25286f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez            bundle->setSingleCrunchInputFile(parameterOne.c_str());
25296f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez            bundle->setSingleCrunchOutputFile(parameterTwo.c_str());
25306f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez            std::cout << "Crunching " << parameterOne << std::endl;
25316f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez            if (doSingleCrunch(bundle) != NO_ERROR) {
25326f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez                std::cout << "Error" << std::endl;
25336f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez            }
25346f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez            std::cout << "Done" << std::endl;
25356f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez        } else {
25366f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez            // in case of invalid command, just bail out.
25376f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez            std::cerr << "Unknown command" << std::endl;
25386f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez            return -1;
25396f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez        }
25406f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez    }
25416f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez    return -1;
25426f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez}
25436f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez
2544282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskichar CONSOLE_DATA[2925] = {
2545282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2546282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 95, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2547282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2548282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32,
2549282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 63,
2550282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    86, 35, 40, 46, 46, 95, 95, 95, 95, 97, 97, 44, 32, 46, 124, 42, 33, 83,
2551282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    62, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2552282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 46, 58, 59, 61, 59, 61, 81,
2554282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 66, 96, 61, 61, 58, 46, 46, 46, 58, 32, 32, 32, 32, 32, 32,
2555282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32,
2556282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2557282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 46, 61, 59, 59, 59, 58, 106, 81, 81, 81, 81, 102, 59, 61, 59,
2558282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 61, 61, 61, 58, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2559282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2560282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59,
2561282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 58, 109, 81, 81, 81, 81, 61, 59, 59, 59, 59, 59, 58, 59, 59, 46, 32,
2562282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2563282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2564282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 60, 81, 81, 81, 81, 87,
2565282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    58, 59, 59, 59, 59, 59, 59, 61, 119, 44, 32, 32, 32, 32, 32, 32, 32, 32,
2566282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32,
2567282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46,
2568282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    47, 61, 59, 59, 58, 100, 81, 81, 81, 81, 35, 58, 59, 59, 59, 59, 59, 58,
2569282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    121, 81, 91, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2570282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2571282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 109, 58, 59, 59, 61, 81, 81,
2572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 109, 58, 59, 59, 59, 59, 61, 109, 81, 81, 76, 46, 32, 32, 32,
2573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32,
2574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 41, 87, 59, 61, 59, 41, 81, 81, 81, 81, 81, 81, 59, 61, 59,
2576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 58, 109, 81, 81, 87, 39, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 60, 81, 91, 59,
2579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 61, 81, 81, 81, 81, 81, 87, 43, 59, 58, 59, 60, 81, 81, 81, 76, 32,
2580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 52, 91, 58, 45, 59, 87, 81, 81, 81, 81,
2583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    70, 58, 58, 58, 59, 106, 81, 81, 81, 91, 32, 32, 32, 32, 32, 32, 32, 32,
2584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32,
2585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 93, 40, 32, 46, 59, 100, 81, 81, 81, 81, 40, 58, 46, 46, 58, 100, 81,
2587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 68, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 46, 46, 46, 32, 46, 46, 46, 32, 46, 32, 46, 45, 91, 59, 61, 58, 109,
2590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 87, 46, 58, 61, 59, 60, 81, 81, 80, 32, 32, 32, 32, 32, 32,
2591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32,
2592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 46, 46, 61, 59, 61, 61, 61, 59, 61, 61, 59,
2593282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 58, 58, 46, 46, 41, 58, 59, 58, 81, 81, 81, 81, 69, 58, 59, 59,
2594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    60, 81, 81, 68, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 58, 59,
2596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    61, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 61, 46,
2597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    61, 59, 93, 81, 81, 81, 81, 107, 58, 59, 58, 109, 87, 68, 96, 32, 32, 32,
2598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 10, 32, 32, 32, 46, 60, 61, 61, 59, 59, 59, 59, 59, 59, 59, 59,
2600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 59, 59, 59, 59, 58, 58, 58, 115, 109, 68, 41, 36, 81,
2601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    109, 46, 61, 61, 81, 69, 96, 46, 58, 58, 46, 58, 46, 46, 32, 32, 32, 32,
2602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 46, 32, 95, 81,
2603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    67, 61, 61, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
2604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 58, 68, 39, 61, 105, 61, 63, 81, 119, 58, 106, 80, 32, 58,
2605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    61, 59, 59, 61, 59, 61, 59, 61, 46, 95, 32, 32, 32, 32, 32, 32, 32, 32,
2606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 10, 32, 32, 36, 81, 109, 105, 59, 61, 59, 59, 59,
2607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 46, 58, 37,
2608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    73, 108, 108, 62, 52, 81, 109, 34, 32, 61, 59, 59, 59, 59, 59, 59, 59, 59,
2609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 61, 59, 61, 61, 46, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10,
2610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 46, 45, 57, 101, 43, 43, 61, 61, 59, 59, 59, 59, 59, 59, 61, 59, 59,
2611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 59, 59, 58, 97, 46, 61, 108, 62, 126, 58, 106, 80, 96,
2612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    46, 61, 61, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 61,
2613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    97, 103, 97, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 45, 46, 32,
2614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    46, 32, 32, 32, 32, 32, 32, 32, 32, 45, 45, 45, 58, 59, 59, 59, 59, 61,
2615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    119, 81, 97, 124, 105, 124, 124, 39, 126, 95, 119, 58, 61, 58, 59, 59, 59,
2616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 119, 81, 81, 99, 32, 32,
2617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 58, 59, 59, 58, 106, 81, 81, 81, 109, 119,
2619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    119, 119, 109, 109, 81, 81, 122, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59,
2620282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 58, 115, 81, 87, 81, 102, 32, 32, 32, 32, 32, 32, 10,
2621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 61, 58, 59, 61, 81, 81, 81, 81, 81, 81, 87, 87, 81, 81, 81, 81,
2623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 58, 59, 59, 59, 59, 59, 59, 59, 59, 58, 45, 45, 45, 59, 59, 59, 41,
2624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    87, 66, 33, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32,
2625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 59, 59, 93, 81,
2626282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 40, 58, 59, 59, 59, 58,
2627282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    45, 32, 46, 32, 32, 32, 32, 32, 46, 32, 126, 96, 32, 32, 32, 32, 32, 32,
2628282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2629282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 58, 61, 59, 58, 81, 81, 81, 81, 81, 81, 81, 81,
2630282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 81, 81, 40, 58, 59, 59, 59, 58, 32, 32, 32, 32, 32, 32, 32,
2631282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32,
2632282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58,
2633282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 58, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 40, 58,
2634282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 46, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 59, 60, 81, 81, 81, 81,
2637282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 81, 81, 81, 81, 81, 81, 59, 61, 59, 59, 61, 32, 32, 32, 32,
2638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 58, 59, 59, 93, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
2641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 40, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32,
2643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 58, 106,
2644282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 76, 58, 59, 59, 59,
2645282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 61, 58, 58, 81, 81, 81, 81, 81, 81, 81, 81,
2648282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 81, 81, 87, 58, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32,
2649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32,
2650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    58, 59, 61, 41, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 87, 59,
2652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    61, 58, 59, 59, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 58, 61, 81, 81, 81,
2655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 81, 81, 81, 81, 81, 81, 107, 58, 59, 59, 59, 59, 58, 32, 32,
2656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 58, 59, 59, 58, 51, 81, 81, 81, 81, 81, 81, 81, 81, 81,
2659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 102, 94, 59, 59, 59, 59, 59, 61, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32,
2661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 59,
2662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 43, 63, 36, 81, 81, 81, 87, 64, 86, 102, 58, 59, 59, 59, 59, 59,
2663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 59, 59, 59, 59, 43, 33,
2666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    58, 126, 126, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 32, 46, 32, 32,
2667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32,
2668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46,
2669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    61, 59, 59, 59, 58, 45, 58, 61, 59, 58, 58, 58, 61, 59, 59, 59, 59, 59,
2670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 59, 59, 58, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32,
2671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32,
2672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 59, 59, 58, 95,
2673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 45, 61, 59, 61, 59, 59, 59, 59, 59, 59, 59, 45, 58, 59, 59, 59, 59,
2674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    61, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2676282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 58, 61, 59, 59, 59, 59, 59, 61, 59, 61, 46, 46, 32, 45, 45, 45,
2677282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 58, 45, 45, 46, 58, 59, 59, 59, 59, 59, 59, 61, 46, 32, 32, 32, 32,
2678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32,
2679282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 58, 59, 59, 59, 59,
2680282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 61, 59, 46, 32, 32, 46, 32, 46, 32, 58, 61, 59, 59,
2681282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 59, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2682282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2683282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 45, 59, 59, 59, 59, 59, 59, 59, 59, 58, 32,
2684282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59, 59, 58, 32,
2685282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10,
2686282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2687282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    46, 61, 59, 59, 59, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 61,
2688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    46, 61, 59, 59, 59, 59, 59, 59, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32,
2690282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59,
2691282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 32, 46, 61, 58, 59, 59, 59, 59,
2692282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2693282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2694282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 58, 59, 59, 59, 59, 59, 59, 59, 59, 46, 46, 32, 32, 32,
2695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59, 59, 45, 32, 32, 32, 32, 32,
2696282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32,
2697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 32, 45, 61,
2698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 58, 32, 46, 32, 32, 32, 32, 32, 32, 32, 58, 59, 59,
2699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 58, 45, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2700282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 45, 45, 45, 45, 32, 46, 32,
2702282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 45, 61, 59, 58, 45, 45, 32, 32, 32,
2703282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2704282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2705282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2706282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 46, 32, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2707282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10
2708282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski  };
2709