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
218b8dc7bc582ee4acd9d6c1379701a002c5ddbe323Andreas Gampe#ifdef HAVE_ANDROID_OS
219b8dc7bc582ee4acd9d6c1379701a002c5ddbe323Andreas Gampe        static const bool kHaveAndroidOs = true;
220b8dc7bc582ee4acd9d6c1379701a002c5ddbe323Andreas Gampe#else
221b8dc7bc582ee4acd9d6c1379701a002c5ddbe323Andreas Gampe        static const bool kHaveAndroidOs = false;
222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif
223b8dc7bc582ee4acd9d6c1379701a002c5ddbe323Andreas Gampe        const ResTable& res = assets.getResources(false);
224b8dc7bc582ee4acd9d6c1379701a002c5ddbe323Andreas Gampe        if (!kHaveAndroidOs) {
225b8dc7bc582ee4acd9d6c1379701a002c5ddbe323Andreas Gampe            printf("\nResource table:\n");
226b8dc7bc582ee4acd9d6c1379701a002c5ddbe323Andreas Gampe            res.print(false);
227b8dc7bc582ee4acd9d6c1379701a002c5ddbe323Andreas Gampe        }
228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Asset* manifestAsset = assets.openNonAsset("AndroidManifest.xml",
230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                   Asset::ACCESS_BUFFER);
231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (manifestAsset == NULL) {
232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("\nNo AndroidManifest.xml found.\n");
233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("\nAndroid manifest:\n");
235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ResXMLTree tree;
236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            tree.setTo(manifestAsset->getBuffer(true),
237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       manifestAsset->getLength());
238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printXMLBlock(&tree);
239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        delete manifestAsset;
241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    result = 0;
244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail:
246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    delete zip;
247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return result;
248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
250ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinskistatic void printResolvedResourceAttribute(const ResTable& resTable, const ResXMLTree& tree,
25176327314d2238e105f8b94909f9c0cf85caca318Maurice Chu        uint32_t attrRes, String8 attrLabel, String8* outError)
25276327314d2238e105f8b94909f9c0cf85caca318Maurice Chu{
25376327314d2238e105f8b94909f9c0cf85caca318Maurice Chu    Res_value value;
254ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski    AaptXml::getResolvedResourceAttribute(resTable, tree, attrRes, &value, outError);
25576327314d2238e105f8b94909f9c0cf85caca318Maurice Chu    if (*outError != "") {
25676327314d2238e105f8b94909f9c0cf85caca318Maurice Chu        *outError = "error print resolved resource attribute";
25776327314d2238e105f8b94909f9c0cf85caca318Maurice Chu        return;
25876327314d2238e105f8b94909f9c0cf85caca318Maurice Chu    }
25976327314d2238e105f8b94909f9c0cf85caca318Maurice Chu    if (value.dataType == Res_value::TYPE_STRING) {
260ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski        String8 result = AaptXml::getResolvedAttribute(resTable, tree, attrRes, outError);
2612675f769673f69b0661ddee346292f25cb30a296Maurice Chu        printf("%s='%s'", attrLabel.string(),
2622675f769673f69b0661ddee346292f25cb30a296Maurice Chu                ResTable::normalizeForOutput(result.string()).string());
26376327314d2238e105f8b94909f9c0cf85caca318Maurice Chu    } else if (Res_value::TYPE_FIRST_INT <= value.dataType &&
26476327314d2238e105f8b94909f9c0cf85caca318Maurice Chu            value.dataType <= Res_value::TYPE_LAST_INT) {
26576327314d2238e105f8b94909f9c0cf85caca318Maurice Chu        printf("%s='%d'", attrLabel.string(), value.data);
26676327314d2238e105f8b94909f9c0cf85caca318Maurice Chu    } else {
26776327314d2238e105f8b94909f9c0cf85caca318Maurice Chu        printf("%s='0x%x'", attrLabel.string(), (int)value.data);
26876327314d2238e105f8b94909f9c0cf85caca318Maurice Chu    }
26976327314d2238e105f8b94909f9c0cf85caca318Maurice Chu}
27076327314d2238e105f8b94909f9c0cf85caca318Maurice Chu
271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// These are attribute resource constants for the platform, as found
272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// in android.R.attr
273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskienum {
274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    LABEL_ATTR = 0x01010001,
275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ICON_ATTR = 0x01010002,
276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    NAME_ATTR = 0x01010003,
277a5018c900f126ee8424c82497f32983873db741bAdam Lesinski    PERMISSION_ATTR = 0x01010006,
2789d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski    EXPORTED_ATTR = 0x01010010,
2799d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski    GRANT_URI_PERMISSIONS_ATTR = 0x0101001b,
28094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    RESOURCE_ATTR = 0x01010025,
281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    DEBUGGABLE_ATTR = 0x0101000f,
282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    VALUE_ATTR = 0x01010024,
283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    VERSION_CODE_ATTR = 0x0101021b,
284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    VERSION_NAME_ATTR = 0x0101021c,
285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    SCREEN_ORIENTATION_ATTR = 0x0101001e,
286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    MIN_SDK_VERSION_ATTR = 0x0101020c,
287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    MAX_SDK_VERSION_ATTR = 0x01010271,
288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    REQ_TOUCH_SCREEN_ATTR = 0x01010227,
289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    REQ_KEYBOARD_TYPE_ATTR = 0x01010228,
290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    REQ_HARD_KEYBOARD_ATTR = 0x01010229,
291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    REQ_NAVIGATION_ATTR = 0x0101022a,
292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    REQ_FIVE_WAY_NAV_ATTR = 0x01010232,
293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    TARGET_SDK_VERSION_ATTR = 0x01010270,
294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    TEST_ONLY_ATTR = 0x01010272,
295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ANY_DENSITY_ATTR = 0x0101026c,
296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    GL_ES_VERSION_ATTR = 0x01010281,
297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    SMALL_SCREEN_ATTR = 0x01010284,
298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    NORMAL_SCREEN_ATTR = 0x01010285,
299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    LARGE_SCREEN_ATTR = 0x01010286,
300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    XLARGE_SCREEN_ATTR = 0x010102bf,
301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    REQUIRED_ATTR = 0x0101028e,
302caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski    INSTALL_LOCATION_ATTR = 0x010102b7,
303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    SCREEN_SIZE_ATTR = 0x010102ca,
304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    SCREEN_DENSITY_ATTR = 0x010102cb,
305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    REQUIRES_SMALLEST_WIDTH_DP_ATTR = 0x01010364,
306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    COMPATIBLE_WIDTH_LIMIT_DP_ATTR = 0x01010365,
307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    LARGEST_WIDTH_LIMIT_DP_ATTR = 0x01010366,
308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    PUBLIC_KEY_ATTR = 0x010103a6,
30994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    CATEGORY_ATTR = 0x010103e8,
3100a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn    BANNER_ATTR = 0x10103f2,
311d9b1cad71e8aaf94e7738d2e47d3a06daa3cdf2dTim Kilbourn    ISGAME_ATTR = 0x10103f4,
312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski};
313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3142675f769673f69b0661ddee346292f25cb30a296Maurice ChuString8 getComponentName(String8 &pkgName, String8 &componentName) {
315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t idx = componentName.find(".");
316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String8 retStr(pkgName);
317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (idx == 0) {
318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        retStr += componentName;
319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else if (idx < 0) {
320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        retStr += ".";
321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        retStr += componentName;
322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
3232675f769673f69b0661ddee346292f25cb30a296Maurice Chu        return componentName;
324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3252675f769673f69b0661ddee346292f25cb30a296Maurice Chu    return retStr;
326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3289cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinskistatic void printCompatibleScreens(ResXMLTree& tree, String8* outError) {
329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t len;
330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ResXMLTree::event_code_t code;
331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int depth = 0;
332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool first = true;
333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    printf("compatible-screens:");
334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (code == ResXMLTree::END_TAG) {
336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            depth--;
337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (depth < 0) {
338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                break;
339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (code != ResXMLTree::START_TAG) {
343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        depth++;
3469cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski        const char16_t* ctag16 = tree.getElementName(&len);
3479cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski        if (ctag16 == NULL) {
3489cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski            *outError = "failed to get XML element name (bad string pool)";
3499cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski            return;
3509cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski        }
3519cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski        String8 tag(ctag16);
352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (tag == "screen") {
353ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski            int32_t screenSize = AaptXml::getIntegerAttribute(tree,
354ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                    SCREEN_SIZE_ATTR);
355ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski            int32_t screenDensity = AaptXml::getIntegerAttribute(tree,
356ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                    SCREEN_DENSITY_ATTR);
357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (screenSize > 0 && screenDensity > 0) {
358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!first) {
359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    printf(",");
360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                first = false;
362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("'%d/%d'", screenSize, screenDensity);
363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    printf("\n");
367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
36958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinskistatic void printUsesPermission(const String8& name, bool optional=false, int maxSdkVersion=-1) {
37058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski    printf("uses-permission: name='%s'", ResTable::normalizeForOutput(name.string()).string());
37158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski    if (maxSdkVersion != -1) {
37258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski         printf(" maxSdkVersion='%d'", maxSdkVersion);
37358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski    }
37458f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski    printf("\n");
37558f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski
37658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski    if (optional) {
37758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski        printf("optional-permission: name='%s'",
37858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                ResTable::normalizeForOutput(name.string()).string());
37958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski        if (maxSdkVersion != -1) {
38058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski            printf(" maxSdkVersion='%d'", maxSdkVersion);
38158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski        }
38258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski        printf("\n");
38358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski    }
38458f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski}
38558f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski
38658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinskistatic void printUsesImpliedPermission(const String8& name, const String8& reason) {
38758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski    printf("uses-implied-permission: name='%s' reason='%s'\n",
38858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski            ResTable::normalizeForOutput(name.string()).string(),
38958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski            ResTable::normalizeForOutput(reason.string()).string());
39058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski}
39158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski
39294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam LesinskiVector<String8> getNfcAidCategories(AssetManager& assets, String8 xmlPath, bool offHost,
39394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski        String8 *outError = NULL)
39494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski{
39594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    Asset* aidAsset = assets.openNonAsset(xmlPath, Asset::ACCESS_BUFFER);
39694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    if (aidAsset == NULL) {
39794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski        if (outError != NULL) *outError = "xml resource does not exist";
39894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski        return Vector<String8>();
39994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    }
40094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
40194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    const String8 serviceTagName(offHost ? "offhost-apdu-service" : "host-apdu-service");
40294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
40394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    bool withinApduService = false;
40494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    Vector<String8> categories;
40594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
40694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    String8 error;
40794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    ResXMLTree tree;
40894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    tree.setTo(aidAsset->getBuffer(true), aidAsset->getLength());
40994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
41094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    size_t len;
41194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    int depth = 0;
41294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    ResXMLTree::event_code_t code;
41394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
41494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski        if (code == ResXMLTree::END_TAG) {
41594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            depth--;
4169cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski            const char16_t* ctag16 = tree.getElementName(&len);
4179cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski            if (ctag16 == NULL) {
4189cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                *outError = "failed to get XML element name (bad string pool)";
4199cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                return Vector<String8>();
4209cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski            }
4219cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski            String8 tag(ctag16);
42294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
42394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            if (depth == 0 && tag == serviceTagName) {
42494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                withinApduService = false;
42594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            }
42694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
42794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski        } else if (code == ResXMLTree::START_TAG) {
42894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            depth++;
4299cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski            const char16_t* ctag16 = tree.getElementName(&len);
4309cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski            if (ctag16 == NULL) {
4319cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                *outError = "failed to get XML element name (bad string pool)";
4329cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                return Vector<String8>();
4339cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski            }
4349cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski            String8 tag(ctag16);
43594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
43694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            if (depth == 1) {
43794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                if (tag == serviceTagName) {
43894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    withinApduService = true;
43994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                }
44094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            } else if (depth == 2 && withinApduService) {
44194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                if (tag == "aid-group") {
442ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                    String8 category = AaptXml::getAttribute(tree, CATEGORY_ATTR, &error);
44394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    if (error != "") {
44494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        if (outError != NULL) *outError = error;
44594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        return Vector<String8>();
44694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    }
44794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
44894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    categories.add(category);
44994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                }
45094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            }
45194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski        }
45294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    }
45394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    aidAsset->close();
45494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski    return categories;
45594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski}
45694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
4579d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinskistatic void printComponentPresence(const char* componentName) {
4589d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski    printf("provides-component:'%s'\n", componentName);
4599d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski}
4609d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski
4612c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski/**
4622c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * Represents a feature that has been automatically added due to
4632c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * a pre-requisite or some other reason.
4642c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski */
4652c72b6822debb08fe997926eedc110f62d287d34Adam Lesinskistruct ImpliedFeature {
4662c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    /**
4672c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski     * Name of the implied feature.
4682c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski     */
4692c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    String8 name;
4702c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
4712c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    /**
4722c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski     * List of human-readable reasons for why this feature was implied.
4732c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski     */
4742c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    SortedVector<String8> reasons;
4752c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski};
4762c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
4772c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski/**
4782c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * Represents a <feature-group> tag in the AndroidManifest.xml
4792c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski */
4802c72b6822debb08fe997926eedc110f62d287d34Adam Lesinskistruct FeatureGroup {
481d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski    FeatureGroup() : openGLESVersion(-1) {}
482d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski
4832c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    /**
4842c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski     * Human readable label
4852c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski     */
4862c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    String8 label;
4872c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
4882c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    /**
4892c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski     * Explicit features defined in the group
4902c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski     */
4912c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    KeyedVector<String8, bool> features;
492d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski
493d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski    /**
494d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski     * OpenGL ES version required
495d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski     */
496d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski    int openGLESVersion;
4972c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski};
4982c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
4992c72b6822debb08fe997926eedc110f62d287d34Adam Lesinskistatic void addImpliedFeature(KeyedVector<String8, ImpliedFeature>* impliedFeatures,
5002c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        const char* name, const char* reason) {
5012c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    String8 name8(name);
5022c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    ssize_t idx = impliedFeatures->indexOfKey(name8);
5032c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    if (idx < 0) {
5042c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        idx = impliedFeatures->add(name8, ImpliedFeature());
5052c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        impliedFeatures->editValueAt(idx).name = name8;
5062c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    }
5072c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    impliedFeatures->editValueAt(idx).reasons.add(String8(reason));
5082c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski}
5092c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
5102c72b6822debb08fe997926eedc110f62d287d34Adam Lesinskistatic void printFeatureGroup(const FeatureGroup& grp,
5112c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        const KeyedVector<String8, ImpliedFeature>* impliedFeatures = NULL) {
5122c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    printf("feature-group: label='%s'\n", grp.label.string());
5132c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
514d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski    if (grp.openGLESVersion > 0) {
515d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski        printf("  uses-gl-es: '0x%x'\n", grp.openGLESVersion);
516d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski    }
517d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski
5182c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    const size_t numFeatures = grp.features.size();
5192c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski    for (size_t i = 0; i < numFeatures; i++) {
52073a05114b051c6dcf5e5126ac94eaf8cac0ab289Adam Lesinski        const bool required = grp.features[i];
5212c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
5222c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski        const String8& featureName = grp.features.keyAt(i);
52373a05114b051c6dcf5e5126ac94eaf8cac0ab289Adam Lesinski        printf("  uses-feature%s: name='%s'\n", (required ? "" : "-not-required"),
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);
6246800165351b693fa7e4bcf0f205655f0cd16b361Dan Albert    if (res.getError() != NO_ERROR) {
62525e9d55e964c180ec6e57ba1d977d6c2e1115f5aAdam Lesinski        fprintf(stderr, "ERROR: dump failed because the resource table is invalid/corrupt.\n");
62663e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski        return 1;
62763e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski    }
62863e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski
6292cb761e3ddb9d68ab430013e9cd15ecaab9fbc62Adam Lesinski    // The dynamicRefTable can be null if there are no resources for this asset cookie.
6302cb761e3ddb9d68ab430013e9cd15ecaab9fbc62Adam Lesinski    // This fine.
63163e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski    const DynamicRefTable* dynamicRefTable = res.getDynamicRefTableForCookie(assetsCookie);
632282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
63363e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski    Asset* asset = NULL;
63463e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski
635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (strcmp("resources", option) == 0) {
636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#ifndef HAVE_ANDROID_OS
637282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        res.print(bundle->getValues());
638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif
639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else if (strcmp("strings", option) == 0) {
641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const ResStringPool* pool = res.getTableStringBlock(0);
642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printStringPool(pool);
643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
644282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else if (strcmp("xmltree", option) == 0) {
645282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (bundle->getFileSpecCount() < 3) {
646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: no dump xmltree resource file specified\n");
647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
648282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (int i=2; i<bundle->getFileSpecCount(); i++) {
651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const char* resname = bundle->getFileSpecEntry(i);
65263e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski            ResXMLTree tree(dynamicRefTable);
65363e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski            asset = assets.openNonAsset(assetsCookie, resname, Asset::ACCESS_BUFFER);
654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (asset == NULL) {
655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, "ERROR: dump failed because resource %s found\n", resname);
656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                goto bail;
657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (tree.setTo(asset->getBuffer(true),
660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           asset->getLength()) != NO_ERROR) {
661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, "ERROR: Resource %s is corrupt\n", resname);
662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                goto bail;
663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            tree.restart();
665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printXMLBlock(&tree);
666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            tree.uninit();
667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            delete asset;
668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            asset = NULL;
669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else if (strcmp("xmlstrings", option) == 0) {
672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (bundle->getFileSpecCount() < 3) {
673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: no dump xmltree resource file specified\n");
674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
676282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
677282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (int i=2; i<bundle->getFileSpecCount(); i++) {
678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const char* resname = bundle->getFileSpecEntry(i);
67963e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski            asset = assets.openNonAsset(assetsCookie, resname, Asset::ACCESS_BUFFER);
680282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (asset == NULL) {
681282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, "ERROR: dump failed because resource %s found\n", resname);
682282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                goto bail;
683282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
684282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
68563e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski            ResXMLTree tree(dynamicRefTable);
686282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (tree.setTo(asset->getBuffer(true),
687282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           asset->getLength()) != NO_ERROR) {
688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, "ERROR: Resource %s is corrupt\n", resname);
689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                goto bail;
690282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
691282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printStringPool(&tree.getStrings());
692282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            delete asset;
693282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            asset = NULL;
694282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
696282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
69763e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski        asset = assets.openNonAsset(assetsCookie, "AndroidManifest.xml", Asset::ACCESS_BUFFER);
698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (asset == NULL) {
699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: dump failed because no AndroidManifest.xml found\n");
700282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
702282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
70363e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski        ResXMLTree tree(dynamicRefTable);
704282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (tree.setTo(asset->getBuffer(true),
705282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       asset->getLength()) != NO_ERROR) {
706282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: AndroidManifest.xml is corrupt\n");
707282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
708282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
709282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        tree.restart();
710282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
711282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (strcmp("permissions", option) == 0) {
712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            size_t len;
713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ResXMLTree::event_code_t code;
714282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int depth = 0;
715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
716282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (code == ResXMLTree::END_TAG) {
717282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    depth--;
718282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
719282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
720282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (code != ResXMLTree::START_TAG) {
721282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
722282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
723282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                depth++;
7249cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                const char16_t* ctag16 = tree.getElementName(&len);
7259cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                if (ctag16 == NULL) {
7269cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                    fprintf(stderr, "ERROR: failed to get XML element name (bad string pool)\n");
7279cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                    goto bail;
7289cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                }
7299cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                String8 tag(ctag16);
730282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                //printf("Depth %d tag %s\n", depth, tag.string());
731282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (depth == 1) {
732282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (tag != "manifest") {
733282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n");
734282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        goto bail;
735282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
736ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                    String8 pkg = AaptXml::getAttribute(tree, NULL, "package", NULL);
7372675f769673f69b0661ddee346292f25cb30a296Maurice Chu                    printf("package: %s\n", ResTable::normalizeForOutput(pkg.string()).string());
738282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else if (depth == 2 && tag == "permission") {
739282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8 error;
740ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                    String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
741282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (error != "") {
742282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        fprintf(stderr, "ERROR: %s\n", error.string());
743282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        goto bail;
744282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
7452675f769673f69b0661ddee346292f25cb30a296Maurice Chu                    printf("permission: %s\n",
7462675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            ResTable::normalizeForOutput(name.string()).string());
747282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else if (depth == 2 && tag == "uses-permission") {
748282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8 error;
749ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                    String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (error != "") {
751282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        fprintf(stderr, "ERROR: %s\n", error.string());
752282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        goto bail;
753282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
75458f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesPermission(name,
755ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            AaptXml::getIntegerAttribute(tree, REQUIRED_ATTR, 1) == 0,
756ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            AaptXml::getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR));
757282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
758282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
759282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else if (strcmp("badging", option) == 0) {
760282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Vector<String8> locales;
761282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            res.getLocales(&locales);
762282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
763282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Vector<ResTable_config> configs;
764282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            res.getConfigurations(&configs);
765282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            SortedVector<int> densities;
766282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t NC = configs.size();
767282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t i=0; i<NC; i++) {
768282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                int dens = configs[i].density;
769282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (dens == 0) {
770282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    dens = 160;
771282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                densities.add(dens);
773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
774282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            size_t len;
776282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ResXMLTree::event_code_t code;
777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int depth = 0;
778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 error;
779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool withinActivity = false;
780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool isMainActivity = false;
781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool isLauncherActivity = false;
7820a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn            bool isLeanbackLauncherActivity = false;
783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool isSearchable = false;
784282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool withinApplication = false;
785ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright            bool withinSupportsInput = false;
7862c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski            bool withinFeatureGroup = false;
787282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool withinReceiver = false;
788282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool withinService = false;
7899d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool withinProvider = false;
790282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool withinIntentFilter = false;
791282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasMainActivity = false;
792282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasOtherActivities = false;
793282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasOtherReceivers = false;
794282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasOtherServices = false;
7959d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool hasIntentFilter = false;
7969d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski
797282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasWallpaperService = false;
798282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasImeService = false;
799a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool hasAccessibilityService = false;
800a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool hasPrintService = false;
801282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasWidgetReceivers = false;
802a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool hasDeviceAdminReceiver = false;
80394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            bool hasPaymentService = false;
8049d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool hasDocumentsProvider = false;
8059d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool hasCameraActivity = false;
8069d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool hasCameraSecureActivity = false;
8079d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool hasLauncher = false;
8089d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool hasNotificationListenerService = false;
809eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock            bool hasDreamService = false;
8109d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski
811282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool actMainActivity = false;
812282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool actWidgetReceivers = false;
813a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool actDeviceAdminEnabled = false;
814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool actImeService = false;
815282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool actWallpaperService = false;
816a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool actAccessibilityService = false;
817a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool actPrintService = false;
81894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            bool actHostApduService = false;
81994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            bool actOffHostApduService = false;
8209d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool actDocumentsProvider = false;
8219d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool actNotificationListenerService = false;
822eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock            bool actDreamService = false;
8239d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool actCamera = false;
8249d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool actCameraSecure = false;
8259d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool catLauncher = false;
82694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            bool hasMetaHostPaymentCategory = false;
82794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            bool hasMetaOffHostPaymentCategory = false;
828a5018c900f126ee8424c82497f32983873db741bAdam Lesinski
829a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            // These permissions are required by services implementing services
830a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            // the system binds to (IME, Accessibility, PrintServices, etc.)
831a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool hasBindDeviceAdminPermission = false;
832a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool hasBindInputMethodPermission = false;
833a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool hasBindAccessibilityServicePermission = false;
834a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            bool hasBindPrintServicePermission = false;
83594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            bool hasBindNfcServicePermission = false;
8369d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool hasRequiredSafAttributes = false;
8379d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            bool hasBindNotificationListenerServicePermission = false;
838eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock            bool hasBindDreamServicePermission = false;
839282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
840282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // These two implement the implicit permissions that are granted
841282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // to pre-1.6 applications.
842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasWriteExternalStoragePermission = false;
843282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasReadPhoneStatePermission = false;
844282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
845282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // If an app requests write storage, they will also get read storage.
846282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasReadExternalStoragePermission = false;
847282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
848282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Implement transition to read and write call log.
849282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasReadContactsPermission = false;
850282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasWriteContactsPermission = false;
851282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasReadCallLogPermission = false;
852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool hasWriteCallLogPermission = false;
853282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
854e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski            // If an app declares itself as multiArch, we report the
855e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski            // native libraries differently.
856e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski            bool hasMultiArch = false;
857e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski
858282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // This next group of variables is used to implement a group of
859282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // backward-compatibility heuristics necessitated by the addition of
860282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // some new uses-feature constants in 2.1 and 2.2. In most cases, the
861282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // heuristic is "if an app requests a permission but doesn't explicitly
862282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // request the corresponding <uses-feature>, presume it's there anyway".
8632c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
864282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // 2.2 also added some other features that apps can request, but that
865282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // have no corresponding permission, so we cannot implement any
866282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // back-compatibility heuristic for them. The below are thus unnecessary
867282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // (but are retained here for documentary purposes.)
868282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //bool specCompassFeature = false;
869282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //bool specAccelerometerFeature = false;
870282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //bool specProximityFeature = false;
871282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //bool specAmbientLightFeature = false;
872282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //bool specLiveWallpaperFeature = false;
873282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
874282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int targetSdk = 0;
875282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int smallScreen = 1;
876282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int normalScreen = 1;
877282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int largeScreen = 1;
878282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int xlargeScreen = 1;
879282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int anyDensity = 1;
880282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int requiresSmallestWidthDp = 0;
881282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int compatibleWidthLimitDp = 0;
882282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int largestWidthLimitDp = 0;
883282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 pkg;
884282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 activityName;
885282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 activityLabel;
886282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 activityIcon;
8870a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn            String8 activityBanner;
888282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 receiverName;
889282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 serviceName;
890ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright            Vector<String8> supportedInput;
8912c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
8922c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski            FeatureGroup commonFeatures;
8932c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski            Vector<FeatureGroup> featureGroups;
8942c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski            KeyedVector<String8, ImpliedFeature> impliedFeatures;
8952c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
896282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
897282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (code == ResXMLTree::END_TAG) {
898282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    depth--;
899282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (depth < 2) {
900ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        if (withinSupportsInput && !supportedInput.isEmpty()) {
901ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            printf("supports-input: '");
902ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            const size_t N = supportedInput.size();
903ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            for (size_t i=0; i<N; i++) {
9042675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                printf("%s", ResTable::normalizeForOutput(
9052675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                        supportedInput[i].string()).string());
906ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                if (i != N - 1) {
907ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                    printf("' '");
908ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                } else {
909ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                    printf("'\n");
910ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                }
911ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
912ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            supportedInput.clear();
913ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        }
914282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        withinApplication = false;
915ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        withinSupportsInput = false;
9162c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                        withinFeatureGroup = false;
917282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (depth < 3) {
9180a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                        if (withinActivity && isMainActivity) {
9192675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            String8 aName(getComponentName(pkg, activityName));
9200a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                            if (isLauncherActivity) {
9210a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                printf("launchable-activity:");
9229eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                if (aName.length() > 0) {
9239eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                    printf(" name='%s' ",
9249eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                            ResTable::normalizeForOutput(aName.string()).string());
9250a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                }
9260a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                printf(" label='%s' icon='%s'\n",
9279eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                        ResTable::normalizeForOutput(activityLabel.string()).string(),
9289eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                        ResTable::normalizeForOutput(activityIcon.string()).string());
9290a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                            }
9300a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                            if (isLeanbackLauncherActivity) {
9310a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                printf("leanback-launchable-activity:");
9329eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                if (aName.length() > 0) {
9339eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                    printf(" name='%s' ",
9349eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                            ResTable::normalizeForOutput(aName.string()).string());
9350a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                }
9360a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                printf(" label='%s' icon='%s' banner='%s'\n",
9379eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                        ResTable::normalizeForOutput(activityLabel.string()).string(),
9389eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                        ResTable::normalizeForOutput(activityIcon.string()).string(),
9399eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn                                        ResTable::normalizeForOutput(activityBanner.string()).string());
940282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
941282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
942282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (!hasIntentFilter) {
943282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            hasOtherActivities |= withinActivity;
944282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            hasOtherReceivers |= withinReceiver;
945282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            hasOtherServices |= withinService;
94694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        } else {
94794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            if (withinService) {
94894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                hasPaymentService |= (actHostApduService && hasMetaHostPaymentCategory &&
94994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                        hasBindNfcServicePermission);
95094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                hasPaymentService |= (actOffHostApduService && hasMetaOffHostPaymentCategory &&
95194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                        hasBindNfcServicePermission);
95294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            }
953282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
954282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        withinActivity = false;
955282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        withinService = false;
956282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        withinReceiver = false;
9579d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                        withinProvider = false;
958282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasIntentFilter = false;
9590a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                        isMainActivity = isLauncherActivity = isLeanbackLauncherActivity = false;
960282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (depth < 4) {
961282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (withinIntentFilter) {
962282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (withinActivity) {
963282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasMainActivity |= actMainActivity;
9649d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                hasLauncher |= catLauncher;
9659d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                hasCameraActivity |= actCamera;
9669d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                hasCameraSecureActivity |= actCameraSecure;
9679d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                hasOtherActivities |= !actMainActivity && !actCamera && !actCameraSecure;
968282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (withinReceiver) {
969282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasWidgetReceivers |= actWidgetReceivers;
970a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                hasDeviceAdminReceiver |= (actDeviceAdminEnabled &&
971a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                        hasBindDeviceAdminPermission);
972a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                hasOtherReceivers |= (!actWidgetReceivers && !actDeviceAdminEnabled);
973282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (withinService) {
974282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasImeService |= actImeService;
975282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasWallpaperService |= actWallpaperService;
976a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                hasAccessibilityService |= (actAccessibilityService &&
977a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                        hasBindAccessibilityServicePermission);
978a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                hasPrintService |= (actPrintService && hasBindPrintServicePermission);
9799d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                hasNotificationListenerService |= actNotificationListenerService &&
9809d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                        hasBindNotificationListenerServicePermission;
981eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock                                hasDreamService |= actDreamService && hasBindDreamServicePermission;
982a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                hasOtherServices |= (!actImeService && !actWallpaperService &&
98394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                        !actAccessibilityService && !actPrintService &&
9849d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                        !actHostApduService && !actOffHostApduService &&
9859d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                        !actNotificationListenerService);
9869d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            } else if (withinProvider) {
9879d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                hasDocumentsProvider |= actDocumentsProvider && hasRequiredSafAttributes;
988282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
989282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
990282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        withinIntentFilter = false;
991282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
992282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
993282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
994282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (code != ResXMLTree::START_TAG) {
995282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
996282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
997282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                depth++;
9989cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski
9999cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                const char16_t* ctag16 = tree.getElementName(&len);
10009cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                if (ctag16 == NULL) {
10019cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                    fprintf(stderr, "ERROR: failed to get XML element name (bad string pool)\n");
10029cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                    goto bail;
10039cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                }
10049cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                String8 tag(ctag16);
1005282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                //printf("Depth %d,  %s\n", depth, tag.string());
1006282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (depth == 1) {
1007282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (tag != "manifest") {
1008282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n");
1009282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        goto bail;
1010282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1011ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                    pkg = AaptXml::getAttribute(tree, NULL, "package", NULL);
10122675f769673f69b0661ddee346292f25cb30a296Maurice Chu                    printf("package: name='%s' ",
10132675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            ResTable::normalizeForOutput(pkg.string()).string());
1014ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                    int32_t versionCode = AaptXml::getIntegerAttribute(tree, VERSION_CODE_ATTR,
1015ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            &error);
1016282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (error != "") {
1017ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        fprintf(stderr, "ERROR getting 'android:versionCode' attribute: %s\n",
1018ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                error.string());
1019282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        goto bail;
1020282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1021282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (versionCode > 0) {
1022282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        printf("versionCode='%d' ", versionCode);
1023282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else {
1024282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        printf("versionCode='' ");
1025282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1026ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                    String8 versionName = AaptXml::getResolvedAttribute(res, tree,
1027ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            VERSION_NAME_ATTR, &error);
1028282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (error != "") {
1029ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        fprintf(stderr, "ERROR getting 'android:versionName' attribute: %s\n",
1030ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                error.string());
1031282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        goto bail;
1032282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
103325d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski                    printf("versionName='%s'",
10342675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            ResTable::normalizeForOutput(versionName.string()).string());
103525d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski
1036ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                    String8 splitName = AaptXml::getAttribute(tree, NULL, "split");
103725d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski                    if (!splitName.isEmpty()) {
103825d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski                        printf(" split='%s'", ResTable::normalizeForOutput(
103925d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski                                    splitName.string()).string());
104025d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski                    }
1041ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski
10425283faba4a75a4d1fd9990637d22768e423895e3Adam Lesinski                    String8 platformVersionName = AaptXml::getAttribute(tree, NULL,
10435283faba4a75a4d1fd9990637d22768e423895e3Adam Lesinski                            "platformBuildVersionName");
10445283faba4a75a4d1fd9990637d22768e423895e3Adam Lesinski                    printf(" platformBuildVersionName='%s'", platformVersionName.string());
104525d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski                    printf("\n");
1046caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski
1047ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                    int32_t installLocation = AaptXml::getResolvedIntegerAttribute(res, tree,
1048ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            INSTALL_LOCATION_ATTR, &error);
1049caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                    if (error != "") {
1050caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                        fprintf(stderr, "ERROR getting 'android:installLocation' attribute: %s\n",
1051caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                                error.string());
1052caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                        goto bail;
1053caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                    }
1054caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski
1055caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                    if (installLocation >= 0) {
1056caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                        printf("install-location:'");
1057caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                        switch (installLocation) {
1058caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                            case 0:
1059caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                                printf("auto");
1060caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                                break;
1061caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                            case 1:
1062caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                                printf("internalOnly");
1063caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                                break;
1064caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                            case 2:
1065caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                                printf("preferExternal");
1066caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                                break;
1067caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                            default:
1068caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                                fprintf(stderr, "Invalid installLocation %d\n", installLocation);
1069caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                                goto bail;
1070caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                        }
1071caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                        printf("'\n");
1072caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski                    }
1073282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else if (depth == 2) {
1074282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    withinApplication = false;
1075282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (tag == "application") {
1076282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        withinApplication = true;
1077282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1078282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8 label;
1079282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const size_t NL = locales.size();
1080282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        for (size_t i=0; i<NL; i++) {
1081282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            const char* localeStr =  locales[i].string();
1082282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            assets.setLocale(localeStr != NULL ? localeStr : "");
1083ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            String8 llabel = AaptXml::getResolvedAttribute(res, tree, LABEL_ATTR,
1084ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    &error);
1085282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (llabel != "") {
1086282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                if (localeStr == NULL || strlen(localeStr) == 0) {
1087282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    label = llabel;
10882675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                    printf("application-label:'%s'\n",
10892675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                            ResTable::normalizeForOutput(llabel.string()).string());
1090282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                } else {
1091282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    if (label == "") {
1092282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        label = llabel;
1093282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    }
1094282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    printf("application-label-%s:'%s'\n", localeStr,
10952675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                           ResTable::normalizeForOutput(llabel.string()).string());
1096282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                }
1097282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1098282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1099282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ResTable_config tmpConfig = config;
1101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const size_t ND = densities.size();
1102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        for (size_t i=0; i<ND; i++) {
1103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            tmpConfig.density = densities[i];
1104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            assets.setConfiguration(tmpConfig);
1105ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            String8 icon = AaptXml::getResolvedAttribute(res, tree, ICON_ATTR,
1106ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    &error);
1107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (icon != "") {
11082675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                printf("application-icon-%d:'%s'\n", densities[i],
11092675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                        ResTable::normalizeForOutput(icon.string()).string());
1110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        assets.setConfiguration(config);
1113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1114ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        String8 icon = AaptXml::getResolvedAttribute(res, tree, ICON_ATTR, &error);
1115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (error != "") {
1116ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n",
1117ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    error.string());
1118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            goto bail;
1119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1120ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        int32_t testOnly = AaptXml::getIntegerAttribute(tree, TEST_ONLY_ATTR, 0,
1121ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                &error);
1122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (error != "") {
1123ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            fprintf(stderr, "ERROR getting 'android:testOnly' attribute: %s\n",
1124ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    error.string());
1125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            goto bail;
1126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1127d9b1cad71e8aaf94e7738d2e47d3a06daa3cdf2dTim Kilbourn
1128d9b1cad71e8aaf94e7738d2e47d3a06daa3cdf2dTim Kilbourn                        String8 banner = AaptXml::getResolvedAttribute(res, tree, BANNER_ATTR, &error);
1129d9b1cad71e8aaf94e7738d2e47d3a06daa3cdf2dTim Kilbourn                        if (error != "") {
1130d9b1cad71e8aaf94e7738d2e47d3a06daa3cdf2dTim Kilbourn                            fprintf(stderr, "ERROR getting 'android:banner' attribute: %s\n",
1131d9b1cad71e8aaf94e7738d2e47d3a06daa3cdf2dTim Kilbourn                                    error.string());
1132d9b1cad71e8aaf94e7738d2e47d3a06daa3cdf2dTim Kilbourn                            goto bail;
1133d9b1cad71e8aaf94e7738d2e47d3a06daa3cdf2dTim Kilbourn                        }
11342675f769673f69b0661ddee346292f25cb30a296Maurice Chu                        printf("application: label='%s' ",
11352675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                ResTable::normalizeForOutput(label.string()).string());
1136d9b1cad71e8aaf94e7738d2e47d3a06daa3cdf2dTim Kilbourn                        printf("icon='%s'", ResTable::normalizeForOutput(icon.string()).string());
1137d9b1cad71e8aaf94e7738d2e47d3a06daa3cdf2dTim Kilbourn                        if (banner != "") {
1138d9b1cad71e8aaf94e7738d2e47d3a06daa3cdf2dTim Kilbourn                            printf(" banner='%s'", ResTable::normalizeForOutput(banner.string()).string());
1139d9b1cad71e8aaf94e7738d2e47d3a06daa3cdf2dTim Kilbourn                        }
1140d9b1cad71e8aaf94e7738d2e47d3a06daa3cdf2dTim Kilbourn                        printf("\n");
1141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (testOnly != 0) {
1142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf("testOnly='%d'\n", testOnly);
1143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1145d9b1cad71e8aaf94e7738d2e47d3a06daa3cdf2dTim Kilbourn                        int32_t isGame = AaptXml::getResolvedIntegerAttribute(res, tree,
1146d9b1cad71e8aaf94e7738d2e47d3a06daa3cdf2dTim Kilbourn                                ISGAME_ATTR, 0, &error);
1147d9b1cad71e8aaf94e7738d2e47d3a06daa3cdf2dTim Kilbourn                        if (error != "") {
1148d9b1cad71e8aaf94e7738d2e47d3a06daa3cdf2dTim Kilbourn                            fprintf(stderr, "ERROR getting 'android:isGame' attribute: %s\n",
1149d9b1cad71e8aaf94e7738d2e47d3a06daa3cdf2dTim Kilbourn                                    error.string());
1150d9b1cad71e8aaf94e7738d2e47d3a06daa3cdf2dTim Kilbourn                            goto bail;
1151d9b1cad71e8aaf94e7738d2e47d3a06daa3cdf2dTim Kilbourn                        }
1152d9b1cad71e8aaf94e7738d2e47d3a06daa3cdf2dTim Kilbourn                        if (isGame != 0) {
1153d9b1cad71e8aaf94e7738d2e47d3a06daa3cdf2dTim Kilbourn                            printf("application-isGame\n");
1154d9b1cad71e8aaf94e7738d2e47d3a06daa3cdf2dTim Kilbourn                        }
1155d9b1cad71e8aaf94e7738d2e47d3a06daa3cdf2dTim Kilbourn
1156ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        int32_t debuggable = AaptXml::getResolvedIntegerAttribute(res, tree,
1157ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                DEBUGGABLE_ATTR, 0, &error);
1158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (error != "") {
1159ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            fprintf(stderr, "ERROR getting 'android:debuggable' attribute: %s\n",
1160ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    error.string());
1161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            goto bail;
1162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (debuggable != 0) {
1164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf("application-debuggable\n");
1165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1166e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski
1167e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        // We must search by name because the multiArch flag hasn't been API
1168e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        // frozen yet.
1169e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        int32_t multiArchIndex = tree.indexOfAttribute(RESOURCES_ANDROID_NAMESPACE,
1170e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                                "multiArch");
1171e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        if (multiArchIndex >= 0) {
1172e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                            Res_value value;
1173e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                            if (tree.getAttributeValue(multiArchIndex, &value) != NO_ERROR) {
1174e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                                if (value.dataType >= Res_value::TYPE_FIRST_INT &&
1175e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                                        value.dataType <= Res_value::TYPE_LAST_INT) {
1176e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                                    hasMultiArch = value.data;
1177e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                                }
1178e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                            }
1179e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        }
1180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "uses-sdk") {
1181ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        int32_t code = AaptXml::getIntegerAttribute(tree, MIN_SDK_VERSION_ATTR, &error);
1182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (error != "") {
1183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            error = "";
1184ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            String8 name = AaptXml::getResolvedAttribute(res, tree,
1185ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    MIN_SDK_VERSION_ATTR, &error);
1186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (error != "") {
1187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                fprintf(stderr, "ERROR getting 'android:minSdkVersion' attribute: %s\n",
1188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        error.string());
1189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                goto bail;
1190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (name == "Donut") targetSdk = 4;
11922675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            printf("sdkVersion:'%s'\n",
11932675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                    ResTable::normalizeForOutput(name.string()).string());
1194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else if (code != -1) {
1195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            targetSdk = code;
1196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf("sdkVersion:'%d'\n", code);
1197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1198ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        code = AaptXml::getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR);
1199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (code != -1) {
1200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf("maxSdkVersion:'%d'\n", code);
1201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1202ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        code = AaptXml::getIntegerAttribute(tree, TARGET_SDK_VERSION_ATTR, &error);
1203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (error != "") {
1204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            error = "";
1205ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            String8 name = AaptXml::getResolvedAttribute(res, tree,
1206ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    TARGET_SDK_VERSION_ATTR, &error);
1207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (error != "") {
1208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                fprintf(stderr, "ERROR getting 'android:targetSdkVersion' attribute: %s\n",
1209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        error.string());
1210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                goto bail;
1211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (name == "Donut" && targetSdk < 4) targetSdk = 4;
12132675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            printf("targetSdkVersion:'%s'\n",
12142675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                    ResTable::normalizeForOutput(name.string()).string());
1215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else if (code != -1) {
1216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (targetSdk < code) {
1217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                targetSdk = code;
1218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf("targetSdkVersion:'%d'\n", code);
1220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "uses-configuration") {
1222ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        int32_t reqTouchScreen = AaptXml::getIntegerAttribute(tree,
1223ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                REQ_TOUCH_SCREEN_ATTR, 0);
1224ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        int32_t reqKeyboardType = AaptXml::getIntegerAttribute(tree,
1225ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                REQ_KEYBOARD_TYPE_ATTR, 0);
1226ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        int32_t reqHardKeyboard = AaptXml::getIntegerAttribute(tree,
1227ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                REQ_HARD_KEYBOARD_ATTR, 0);
1228ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        int32_t reqNavigation = AaptXml::getIntegerAttribute(tree,
1229ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                REQ_NAVIGATION_ATTR, 0);
1230ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        int32_t reqFiveWayNav = AaptXml::getIntegerAttribute(tree,
1231ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                REQ_FIVE_WAY_NAV_ATTR, 0);
1232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        printf("uses-configuration:");
1233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (reqTouchScreen != 0) {
1234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf(" reqTouchScreen='%d'", reqTouchScreen);
1235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (reqKeyboardType != 0) {
1237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf(" reqKeyboardType='%d'", reqKeyboardType);
1238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (reqHardKeyboard != 0) {
1240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf(" reqHardKeyboard='%d'", reqHardKeyboard);
1241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (reqNavigation != 0) {
1243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf(" reqNavigation='%d'", reqNavigation);
1244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (reqFiveWayNav != 0) {
1246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            printf(" reqFiveWayNav='%d'", reqFiveWayNav);
1247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        printf("\n");
1249ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                    } else if (tag == "supports-input") {
1250ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        withinSupportsInput = true;
1251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "supports-screens") {
1252ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        smallScreen = AaptXml::getIntegerAttribute(tree,
1253ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                SMALL_SCREEN_ATTR, 1);
1254ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        normalScreen = AaptXml::getIntegerAttribute(tree,
1255ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                NORMAL_SCREEN_ATTR, 1);
1256ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        largeScreen = AaptXml::getIntegerAttribute(tree,
1257ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                LARGE_SCREEN_ATTR, 1);
1258ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        xlargeScreen = AaptXml::getIntegerAttribute(tree,
1259ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                XLARGE_SCREEN_ATTR, 1);
1260ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        anyDensity = AaptXml::getIntegerAttribute(tree,
1261ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                ANY_DENSITY_ATTR, 1);
1262ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        requiresSmallestWidthDp = AaptXml::getIntegerAttribute(tree,
1263ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                REQUIRES_SMALLEST_WIDTH_DP_ATTR, 0);
1264ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        compatibleWidthLimitDp = AaptXml::getIntegerAttribute(tree,
1265ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                COMPATIBLE_WIDTH_LIMIT_DP_ATTR, 0);
1266ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        largestWidthLimitDp = AaptXml::getIntegerAttribute(tree,
1267ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                LARGEST_WIDTH_LIMIT_DP_ATTR, 0);
12682c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                    } else if (tag == "feature-group") {
12692c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                        withinFeatureGroup = true;
12702c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                        FeatureGroup group;
1271ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        group.label = AaptXml::getResolvedAttribute(res, tree, LABEL_ATTR, &error);
12722c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                        if (error != "") {
12732c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                            fprintf(stderr, "ERROR getting 'android:label' attribute:"
12742c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                    " %s\n", error.string());
12752c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                            goto bail;
12762c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                        }
12772c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                        featureGroups.add(group);
12782c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
1279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "uses-feature") {
1280ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
1281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (name != "" && error == "") {
1282ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            int req = AaptXml::getIntegerAttribute(tree,
1283ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    REQUIRED_ATTR, 1);
1284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
12852c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                            commonFeatures.features.add(name, req);
12862c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                            if (req) {
12872c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                addParentFeatures(&commonFeatures, name);
1288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else {
1290ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            int vers = AaptXml::getIntegerAttribute(tree,
1291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    GL_ES_VERSION_ATTR, &error);
1292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (error == "") {
1293d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                                if (vers > commonFeatures.openGLESVersion) {
1294d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                                    commonFeatures.openGLESVersion = vers;
1295d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                                }
1296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "uses-permission") {
1299ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
1300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (name != "" && error == "") {
1301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (name == "android.permission.CAMERA") {
1302d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                                addImpliedFeature(&impliedFeatures, "android.hardware.camera",
13032c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        String8::format("requested %s permission", name.string())
13042c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        .string());
1305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.ACCESS_FINE_LOCATION") {
13062c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                addImpliedFeature(&impliedFeatures, "android.hardware.location.gps",
13072c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        String8::format("requested %s permission", name.string())
13082c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        .string());
13092c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                addImpliedFeature(&impliedFeatures, "android.hardware.location",
13102c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        String8::format("requested %s permission", name.string())
13112c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        .string());
1312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.ACCESS_MOCK_LOCATION") {
13132c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                addImpliedFeature(&impliedFeatures, "android.hardware.location",
13142c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        String8::format("requested %s permission", name.string())
13152c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        .string());
1316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.ACCESS_COARSE_LOCATION") {
13172c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                addImpliedFeature(&impliedFeatures, "android.hardware.location.network",
13182c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        String8::format("requested %s permission", name.string())
13192c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        .string());
13202c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                addImpliedFeature(&impliedFeatures, "android.hardware.location",
13212c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        String8::format("requested %s permission", name.string())
13222c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        .string());
1323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" ||
1324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.INSTALL_LOCATION_PROVIDER") {
13252c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                addImpliedFeature(&impliedFeatures, "android.hardware.location",
13262c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        String8::format("requested %s permission", name.string())
13272c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        .string());
1328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.BLUETOOTH" ||
1329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.BLUETOOTH_ADMIN") {
13302c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                if (targetSdk > 4) {
13312c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                    addImpliedFeature(&impliedFeatures, "android.hardware.bluetooth",
13322c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                            String8::format("requested %s permission", name.string())
13332c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                            .string());
13342c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                    addImpliedFeature(&impliedFeatures, "android.hardware.bluetooth",
13352c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                            "targetSdkVersion > 4");
13362c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                }
1337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.RECORD_AUDIO") {
13382c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                addImpliedFeature(&impliedFeatures, "android.hardware.microphone",
13392c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        String8::format("requested %s permission", name.string())
13402c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        .string());
1341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.ACCESS_WIFI_STATE" ||
1342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.CHANGE_WIFI_STATE" ||
1343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.CHANGE_WIFI_MULTICAST_STATE") {
13442c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                addImpliedFeature(&impliedFeatures, "android.hardware.wifi",
13452c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        String8::format("requested %s permission", name.string())
13462c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        .string());
1347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.CALL_PHONE" ||
1348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.CALL_PRIVILEGED" ||
1349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.MODIFY_PHONE_STATE" ||
1350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.PROCESS_OUTGOING_CALLS" ||
1351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.READ_SMS" ||
1352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.RECEIVE_SMS" ||
1353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.RECEIVE_MMS" ||
1354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.RECEIVE_WAP_PUSH" ||
1355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.SEND_SMS" ||
1356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.WRITE_APN_SETTINGS" ||
1357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       name == "android.permission.WRITE_SMS") {
13582c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                addImpliedFeature(&impliedFeatures, "android.hardware.telephony",
13592c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                        String8("requested a telephony permission").string());
1360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.WRITE_EXTERNAL_STORAGE") {
1361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasWriteExternalStoragePermission = true;
1362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.READ_EXTERNAL_STORAGE") {
1363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasReadExternalStoragePermission = true;
1364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.READ_PHONE_STATE") {
1365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasReadPhoneStatePermission = true;
1366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.READ_CONTACTS") {
1367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasReadContactsPermission = true;
1368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.WRITE_CONTACTS") {
1369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasWriteContactsPermission = true;
1370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.READ_CALL_LOG") {
1371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasReadCallLogPermission = true;
1372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else if (name == "android.permission.WRITE_CALL_LOG") {
1373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasWriteCallLogPermission = true;
1374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
137558f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski
137658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                            printUsesPermission(name,
1377ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    AaptXml::getIntegerAttribute(tree, REQUIRED_ATTR, 1) == 0,
1378ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    AaptXml::getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR));
137958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                       } else {
1380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    error.string());
1382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            goto bail;
1383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "uses-package") {
1385ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
1386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (name != "" && error == "") {
13872675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            printf("uses-package:'%s'\n",
13882675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                    ResTable::normalizeForOutput(name.string()).string());
1389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else {
1390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    error.string());
1392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                goto bail;
1393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "original-package") {
1395ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
1396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (name != "" && error == "") {
13972675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            printf("original-package:'%s'\n",
13982675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                    ResTable::normalizeForOutput(name.string()).string());
1399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else {
1400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    error.string());
1402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                goto bail;
1403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "supports-gl-texture") {
1405ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
1406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (name != "" && error == "") {
14072675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            printf("supports-gl-texture:'%s'\n",
14082675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                    ResTable::normalizeForOutput(name.string()).string());
1409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else {
1410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    error.string());
1412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                goto bail;
1413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "compatible-screens") {
14159cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                        printCompatibleScreens(tree, &error);
14169cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                        if (error != "") {
14179cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                            fprintf(stderr, "ERROR getting compatible screens: %s\n",
14189cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                                    error.string());
14199cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                            goto bail;
14209cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski                        }
1421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        depth--;
1422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (tag == "package-verifier") {
1423ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
1424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (name != "" && error == "") {
1425ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            String8 publicKey = AaptXml::getAttribute(tree, PUBLIC_KEY_ATTR, &error);
1426282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (publicKey != "" && error == "") {
1427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                printf("package-verifier: name='%s' publicKey='%s'\n",
14282675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                        ResTable::normalizeForOutput(name.string()).string(),
14292675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                        ResTable::normalizeForOutput(publicKey.string()).string());
1430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1433ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                } else if (depth == 3) {
1434282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    withinActivity = false;
1435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    withinReceiver = false;
1436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    withinService = false;
14379d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                    withinProvider = false;
1438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasIntentFilter = false;
143994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    hasMetaHostPaymentCategory = false;
144094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    hasMetaOffHostPaymentCategory = false;
144194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    hasBindDeviceAdminPermission = false;
144294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    hasBindInputMethodPermission = false;
144394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    hasBindAccessibilityServicePermission = false;
144494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    hasBindPrintServicePermission = false;
144594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    hasBindNfcServicePermission = false;
14469d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                    hasRequiredSafAttributes = false;
14479d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                    hasBindNotificationListenerServicePermission = false;
1448eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock                    hasBindDreamServicePermission = false;
1449ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                    if (withinApplication) {
1450ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        if(tag == "activity") {
1451ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            withinActivity = true;
1452ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            activityName = AaptXml::getAttribute(tree, NAME_ATTR, &error);
1453ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (error != "") {
1454ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1455ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        error.string());
1456ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                goto bail;
1457ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
1458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1459ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            activityLabel = AaptXml::getResolvedAttribute(res, tree, LABEL_ATTR,
1460ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    &error);
1461ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (error != "") {
1462ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                fprintf(stderr, "ERROR getting 'android:label' attribute: %s\n",
1463ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        error.string());
1464ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                goto bail;
1465ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
1466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1467ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            activityIcon = AaptXml::getResolvedAttribute(res, tree, ICON_ATTR,
1468ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    &error);
1469ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (error != "") {
1470ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n",
1471ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        error.string());
1472ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                goto bail;
1473ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
1474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1475ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            activityBanner = AaptXml::getResolvedAttribute(res, tree, BANNER_ATTR,
1476ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    &error);
14770a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                            if (error != "") {
14780a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                fprintf(stderr, "ERROR getting 'android:banner' attribute: %s\n",
14790a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                        error.string());
14800a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                goto bail;
14810a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                            }
14820a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn
1483ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            int32_t orien = AaptXml::getResolvedIntegerAttribute(res, tree,
1484ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                    SCREEN_ORIENTATION_ATTR, &error);
1485ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (error == "") {
1486ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                if (orien == 0 || orien == 6 || orien == 8) {
1487ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                    // Requests landscape, sensorLandscape, or reverseLandscape.
14882c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                    addImpliedFeature(&impliedFeatures, "android.hardware.screen.landscape",
14892c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                            "one or more activities have specified a landscape orientation");
1490ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                } else if (orien == 1 || orien == 7 || orien == 9) {
1491ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                    // Requests portrait, sensorPortrait, or reversePortrait.
14922c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                    addImpliedFeature(&impliedFeatures, "android.hardware.screen.portrait",
14932c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                                            "one or more activities have specified a portrait orientation");
1494ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                }
1495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1496ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        } else if (tag == "uses-library") {
1497ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            String8 libraryName = AaptXml::getAttribute(tree, NAME_ATTR, &error);
1498ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (error != "") {
1499ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                fprintf(stderr,
1500ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        "ERROR getting 'android:name' attribute for uses-library"
1501ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        " %s\n", error.string());
1502ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                goto bail;
1503ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
1504ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            int req = AaptXml::getIntegerAttribute(tree,
1505ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    REQUIRED_ATTR, 1);
1506ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            printf("uses-library%s:'%s'\n",
15072675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                    req ? "" : "-not-required", ResTable::normalizeForOutput(
15082675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                            libraryName.string()).string());
1509ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        } else if (tag == "receiver") {
1510ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            withinReceiver = true;
1511ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            receiverName = AaptXml::getAttribute(tree, NAME_ATTR, &error);
1512282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1513ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (error != "") {
1514ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                fprintf(stderr,
1515ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        "ERROR getting 'android:name' attribute for receiver:"
1516ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        " %s\n", error.string());
1517ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                goto bail;
1518ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
1519a5018c900f126ee8424c82497f32983873db741bAdam Lesinski
1520ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            String8 permission = AaptXml::getAttribute(tree, PERMISSION_ATTR,
1521ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    &error);
1522a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            if (error == "") {
1523a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                if (permission == "android.permission.BIND_DEVICE_ADMIN") {
1524a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                    hasBindDeviceAdminPermission = true;
1525a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                }
1526a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            } else {
1527a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                fprintf(stderr, "ERROR getting 'android:permission' attribute for"
1528a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                        " receiver '%s': %s\n", receiverName.string(), error.string());
1529a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            }
1530ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        } else if (tag == "service") {
1531ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            withinService = true;
1532ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            serviceName = AaptXml::getAttribute(tree, NAME_ATTR, &error);
1533282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1534ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (error != "") {
1535ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                fprintf(stderr, "ERROR getting 'android:name' attribute for "
1536ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        "service:%s\n", error.string());
1537ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                goto bail;
1538ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
1539a5018c900f126ee8424c82497f32983873db741bAdam Lesinski
1540ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            String8 permission = AaptXml::getAttribute(tree, PERMISSION_ATTR,
1541ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    &error);
1542a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            if (error == "") {
1543a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                if (permission == "android.permission.BIND_INPUT_METHOD") {
1544a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                    hasBindInputMethodPermission = true;
1545a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                } else if (permission == "android.permission.BIND_ACCESSIBILITY_SERVICE") {
1546a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                    hasBindAccessibilityServicePermission = true;
1547a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                } else if (permission == "android.permission.BIND_PRINT_SERVICE") {
1548a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                    hasBindPrintServicePermission = true;
154994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                } else if (permission == "android.permission.BIND_NFC_SERVICE") {
155094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                    hasBindNfcServicePermission = true;
15519d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                } else if (permission == "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE") {
15529d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                    hasBindNotificationListenerServicePermission = true;
1553eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock                                } else if (permission == "android.permission.BIND_DREAM_SERVICE") {
1554eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock                                    hasBindDreamServicePermission = true;
1555a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                }
1556a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            } else {
1557a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                fprintf(stderr, "ERROR getting 'android:permission' attribute for"
1558a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                        " service '%s': %s\n", serviceName.string(), error.string());
1559a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            }
15609d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                        } else if (tag == "provider") {
15619d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            withinProvider = true;
15629d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski
1563ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            bool exported = AaptXml::getResolvedIntegerAttribute(res, tree,
1564ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    EXPORTED_ATTR, &error);
15659d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            if (error != "") {
15669d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                fprintf(stderr, "ERROR getting 'android:exported' attribute for provider:"
15679d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                        " %s\n", error.string());
15689d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                goto bail;
15699d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            }
15709d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski
1571ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            bool grantUriPermissions = AaptXml::getResolvedIntegerAttribute(
1572ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    res, tree, GRANT_URI_PERMISSIONS_ATTR, &error);
15739d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            if (error != "") {
15749d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                fprintf(stderr, "ERROR getting 'android:grantUriPermissions' attribute for provider:"
15759d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                        " %s\n", error.string());
15769d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                goto bail;
15779d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            }
15789d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski
1579ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            String8 permission = AaptXml::getResolvedAttribute(res, tree,
1580ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    PERMISSION_ATTR, &error);
15819d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            if (error != "") {
15829d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                fprintf(stderr, "ERROR getting 'android:permission' attribute for provider:"
15839d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                        " %s\n", error.string());
15849d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                goto bail;
15859d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            }
15869d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski
15879d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            hasRequiredSafAttributes |= exported && grantUriPermissions &&
15889d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                permission == "android.permission.MANAGE_DOCUMENTS";
15899d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski
1590ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        } else if (bundle->getIncludeMetaData() && tag == "meta-data") {
1591ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            String8 metaDataName = AaptXml::getResolvedAttribute(res, tree,
1592ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    NAME_ATTR, &error);
1593ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (error != "") {
1594ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                fprintf(stderr, "ERROR getting 'android:name' attribute for "
1595ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        "meta-data:%s\n", error.string());
1596ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                goto bail;
1597ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
15982675f769673f69b0661ddee346292f25cb30a296Maurice Chu                            printf("meta-data: name='%s' ",
15992675f769673f69b0661ddee346292f25cb30a296Maurice Chu                                    ResTable::normalizeForOutput(metaDataName.string()).string());
1600ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            printResolvedResourceAttribute(res, tree, VALUE_ATTR, String8("value"),
160176327314d2238e105f8b94909f9c0cf85caca318Maurice Chu                                    &error);
1602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (error != "") {
160376327314d2238e105f8b94909f9c0cf85caca318Maurice Chu                                // Try looking for a RESOURCE_ATTR
160476327314d2238e105f8b94909f9c0cf85caca318Maurice Chu                                error = "";
1605ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                printResolvedResourceAttribute(res, tree, RESOURCE_ATTR,
160676327314d2238e105f8b94909f9c0cf85caca318Maurice Chu                                        String8("resource"), &error);
1607ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                if (error != "") {
160876327314d2238e105f8b94909f9c0cf85caca318Maurice Chu                                    fprintf(stderr, "ERROR getting 'android:value' or "
160976327314d2238e105f8b94909f9c0cf85caca318Maurice Chu                                            "'android:resource' attribute for "
161076327314d2238e105f8b94909f9c0cf85caca318Maurice Chu                                            "meta-data:%s\n", error.string());
1611ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                    goto bail;
1612ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                }
1613ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            }
161476327314d2238e105f8b94909f9c0cf85caca318Maurice Chu                            printf("\n");
1615ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                        } else if (withinSupportsInput && tag == "input-type") {
1616ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
1617ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            if (name != "" && error == "") {
1618ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                supportedInput.add(name);
1619ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                            } else {
1620ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1621ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright                                        error.string());
1622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                goto bail;
1623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
16252c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                    } else if (withinFeatureGroup && tag == "uses-feature") {
1626d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                        FeatureGroup& top = featureGroups.editTop();
1627d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski
1628ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        String8 name = AaptXml::getResolvedAttribute(res, tree, NAME_ATTR, &error);
1629d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                        if (name != "" && error == "") {
1630d3edfde51bd069a63e820282421d1a534fcf00ceAdam Lesinski                            top.features.add(name, true);
1631d3edfde51bd069a63e820282421d1a534fcf00ceAdam Lesinski                            addParentFeatures(&top, name);
1632d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                        } else {
1633ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            int vers = AaptXml::getIntegerAttribute(tree, GL_ES_VERSION_ATTR,
1634ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    &error);
1635d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                            if (error == "") {
1636d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                                if (vers > top.openGLESVersion) {
1637d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                                    top.openGLESVersion = vers;
1638d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                                }
1639d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                            }
16402c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                        }
1641a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                    }
164294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                } else if (depth == 4) {
164394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    if (tag == "intent-filter") {
164494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        hasIntentFilter = true;
164594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        withinIntentFilter = true;
164694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actMainActivity = false;
164794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actWidgetReceivers = false;
164894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actImeService = false;
164994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actWallpaperService = false;
165094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actAccessibilityService = false;
165194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actPrintService = false;
165294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actDeviceAdminEnabled = false;
165394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actHostApduService = false;
165494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        actOffHostApduService = false;
16559d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                        actDocumentsProvider = false;
16569d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                        actNotificationListenerService = false;
1657eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock                        actDreamService = false;
16589d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                        actCamera = false;
16599d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                        actCameraSecure = false;
16609d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                        catLauncher = false;
166194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    } else if (withinService && tag == "meta-data") {
1662ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
166394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        if (error != "") {
166494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            fprintf(stderr, "ERROR getting 'android:name' attribute for"
166594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                    " meta-data tag in service '%s': %s\n", serviceName.string(), error.string());
166694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            goto bail;
166794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        }
166894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
166994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        if (name == "android.nfc.cardemulation.host_apdu_service" ||
167094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                name == "android.nfc.cardemulation.off_host_apdu_service") {
167194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            bool offHost = true;
167294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            if (name == "android.nfc.cardemulation.host_apdu_service") {
167394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                offHost = false;
167494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            }
167594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
1676ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                            String8 xmlPath = AaptXml::getResolvedAttribute(res, tree,
1677ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                                    RESOURCE_ATTR, &error);
167894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            if (error != "") {
167994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                fprintf(stderr, "ERROR getting 'android:resource' attribute for"
168094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                        " meta-data tag in service '%s': %s\n", serviceName.string(), error.string());
168194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                goto bail;
168294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            }
168394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
168494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            Vector<String8> categories = getNfcAidCategories(assets, xmlPath,
168594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                    offHost, &error);
168694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            if (error != "") {
168794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                fprintf(stderr, "ERROR getting AID category for service '%s'\n",
168894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                        serviceName.string());
168994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                goto bail;
169094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            }
169194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski
169294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            const size_t catLen = categories.size();
169394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            for (size_t i = 0; i < catLen; i++) {
169494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                bool paymentCategory = (categories[i] == "payment");
169594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                if (offHost) {
169694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                    hasMetaOffHostPaymentCategory |= paymentCategory;
169794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                } else {
169894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                    hasMetaHostPaymentCategory |= paymentCategory;
169994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                }
170094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            }
170194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                        }
170294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                    }
1703a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                } else if ((depth == 5) && withinIntentFilter) {
1704a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                    String8 action;
1705a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                    if (tag == "action") {
1706ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        action = AaptXml::getAttribute(tree, NAME_ATTR, &error);
1707a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        if (error != "") {
1708a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1709a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                    error.string());
1710a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            goto bail;
1711a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        }
1712a5018c900f126ee8424c82497f32983873db741bAdam Lesinski
1713a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        if (withinActivity) {
1714a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            if (action == "android.intent.action.MAIN") {
1715a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                isMainActivity = true;
1716a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                actMainActivity = true;
17179d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            } else if (action == "android.media.action.STILL_IMAGE_CAMERA" ||
17189d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                    action == "android.media.action.VIDEO_CAMERA") {
17199d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                actCamera = true;
17209d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            } else if (action == "android.media.action.STILL_IMAGE_CAMERA_SECURE") {
17219d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                actCameraSecure = true;
1722282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1723a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        } else if (withinReceiver) {
1724a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            if (action == "android.appwidget.action.APPWIDGET_UPDATE") {
1725a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                actWidgetReceivers = true;
1726a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            } else if (action == "android.app.action.DEVICE_ADMIN_ENABLED") {
1727a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                actDeviceAdminEnabled = true;
1728282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1729a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        } else if (withinService) {
1730a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            if (action == "android.view.InputMethod") {
1731a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                actImeService = true;
1732a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            } else if (action == "android.service.wallpaper.WallpaperService") {
1733a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                actWallpaperService = true;
1734a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            } else if (action == "android.accessibilityservice.AccessibilityService") {
1735a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                actAccessibilityService = true;
1736a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            } else if (action == "android.printservice.PrintService") {
1737a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                actPrintService = true;
173894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            } else if (action == "android.nfc.cardemulation.action.HOST_APDU_SERVICE") {
173994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                actHostApduService = true;
174094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                            } else if (action == "android.nfc.cardemulation.action.OFF_HOST_APDU_SERVICE") {
174194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski                                actOffHostApduService = true;
17429d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            } else if (action == "android.service.notification.NotificationListenerService") {
17439d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                actNotificationListenerService = true;
1744eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock                            } else if (action == "android.service.dreams.DreamService") {
1745eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock                                actDreamService = true;
17469d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            }
17479d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                        } else if (withinProvider) {
17489d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            if (action == "android.content.action.DOCUMENTS_PROVIDER") {
17499d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                actDocumentsProvider = true;
1750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1751282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1752a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        if (action == "android.intent.action.SEARCH") {
1753a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            isSearchable = true;
1754a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        }
1755a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                    }
1756282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1757a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                    if (tag == "category") {
1758ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski                        String8 category = AaptXml::getAttribute(tree, NAME_ATTR, &error);
1759a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        if (error != "") {
1760a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            fprintf(stderr, "ERROR getting 'name' attribute: %s\n",
1761a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                    error.string());
1762a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            goto bail;
1763a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        }
1764a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                        if (withinActivity) {
1765a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                            if (category == "android.intent.category.LAUNCHER") {
1766a5018c900f126ee8424c82497f32983873db741bAdam Lesinski                                isLauncherActivity = true;
17670a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                            } else if (category == "android.intent.category.LEANBACK_LAUNCHER") {
17680a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn                                isLeanbackLauncherActivity = true;
17699d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                            } else if (category == "android.intent.category.HOME") {
17709d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                                catLauncher = true;
1771282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1774282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1776282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Pre-1.6 implicitly granted permission compatibility logic
1778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (targetSdk < 4) {
1779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!hasWriteExternalStoragePermission) {
178058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesPermission(String8("android.permission.WRITE_EXTERNAL_STORAGE"));
178158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesImpliedPermission(String8("android.permission.WRITE_EXTERNAL_STORAGE"),
178258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                            String8("targetSdkVersion < 4"));
1783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasWriteExternalStoragePermission = true;
1784282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!hasReadPhoneStatePermission) {
178658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesPermission(String8("android.permission.READ_PHONE_STATE"));
178758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesImpliedPermission(String8("android.permission.READ_PHONE_STATE"),
178858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                            String8("targetSdkVersion < 4"));
1789282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1790282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1791282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1792282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // If the application has requested WRITE_EXTERNAL_STORAGE, we will
1793282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // force them to always take READ_EXTERNAL_STORAGE as well.  We always
1794282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // do this (regardless of target API version) because we can't have
1795282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // an app with write permission but not read permission.
1796282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!hasReadExternalStoragePermission && hasWriteExternalStoragePermission) {
179758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                printUsesPermission(String8("android.permission.READ_EXTERNAL_STORAGE"));
179858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                printUsesImpliedPermission(String8("android.permission.READ_EXTERNAL_STORAGE"),
179958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                        String8("requested WRITE_EXTERNAL_STORAGE"));
1800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1801282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1802282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Pre-JellyBean call log permission compatibility.
1803282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (targetSdk < 16) {
1804282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!hasReadCallLogPermission && hasReadContactsPermission) {
180558f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesPermission(String8("android.permission.READ_CALL_LOG"));
180658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesImpliedPermission(String8("android.permission.READ_CALL_LOG"),
180758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                            String8("targetSdkVersion < 16 and requested READ_CONTACTS"));
1808282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1809282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!hasWriteCallLogPermission && hasWriteContactsPermission) {
181058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesPermission(String8("android.permission.WRITE_CALL_LOG"));
181158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                    printUsesImpliedPermission(String8("android.permission.WRITE_CALL_LOG"),
181258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski                            String8("targetSdkVersion < 16 and requested WRITE_CONTACTS"));
1813282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1815282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
18162c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski            addImpliedFeature(&impliedFeatures, "android.hardware.touchscreen",
18172c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                    "default feature for all apps");
18182c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
18192c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski            const size_t numFeatureGroups = featureGroups.size();
18202c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski            if (numFeatureGroups == 0) {
18212c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                // If no <feature-group> tags were defined, apply auto-implied features.
18222c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                printFeatureGroup(commonFeatures, &impliedFeatures);
18232c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
18242c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski            } else {
18252c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                // <feature-group> tags are defined, so we ignore implied features and
18262c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                for (size_t i = 0; i < numFeatureGroups; i++) {
18272c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                    FeatureGroup& grp = featureGroups.editItemAt(i);
18282c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
1829d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                    if (commonFeatures.openGLESVersion > grp.openGLESVersion) {
1830d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                        grp.openGLESVersion = commonFeatures.openGLESVersion;
1831d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                    }
1832d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski
18332c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                    // Merge the features defined in the top level (not inside a <feature-group>)
18342c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                    // with this feature group.
18352c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                    const size_t numCommonFeatures = commonFeatures.features.size();
18362c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                    for (size_t j = 0; j < numCommonFeatures; j++) {
18372c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                        if (grp.features.indexOfKey(commonFeatures.features.keyAt(j)) < 0) {
1838d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                            grp.features.add(commonFeatures.features.keyAt(j),
1839d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski                                    commonFeatures.features[j]);
18402c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                        }
1841282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
184373a05114b051c6dcf5e5126ac94eaf8cac0ab289Adam Lesinski                    if (!grp.features.isEmpty()) {
18442c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                        printFeatureGroup(grp);
18452c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski                    }
1846282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1847282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1848282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
18492c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski
1850282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (hasWidgetReceivers) {
18519d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("app-widget");
1852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1853a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            if (hasDeviceAdminReceiver) {
18549d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("device-admin");
1855a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            }
1856282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (hasImeService) {
18579d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("ime");
1858282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1859282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (hasWallpaperService) {
18609d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("wallpaper");
1861282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1862a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            if (hasAccessibilityService) {
18639d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("accessibility");
1864a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            }
1865a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            if (hasPrintService) {
18669d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("print-service");
1867a5018c900f126ee8424c82497f32983873db741bAdam Lesinski            }
186894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            if (hasPaymentService) {
18699d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("payment");
18709d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            }
18719d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            if (isSearchable) {
18729d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("search");
18739d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            }
18749d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            if (hasDocumentsProvider) {
18759d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("document-provider");
18769d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            }
18779d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            if (hasLauncher) {
18789d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("launcher");
18799d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            }
18809d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            if (hasNotificationListenerService) {
18819d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("notification-listener");
18829d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            }
1883eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock            if (hasDreamService) {
1884eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock                printComponentPresence("dream");
1885eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock            }
18869d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            if (hasCameraActivity) {
18879d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("camera");
18889d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            }
18899d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            if (hasCameraSecureActivity) {
18909d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printComponentPresence("camera-secure");
18919d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            }
18929d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski
18939d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski            if (hasMainActivity) {
18949d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski                printf("main\n");
189594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski            }
1896282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (hasOtherActivities) {
1897282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("other-activities\n");
1898282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
18999d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski             if (hasOtherReceivers) {
1900282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("other-receivers\n");
1901282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1902282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (hasOtherServices) {
1903282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("other-services\n");
1904282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1905282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1906282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // For modern apps, if screen size buckets haven't been specified
1907282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // but the new width ranges have, then infer the buckets from them.
1908282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (smallScreen > 0 && normalScreen > 0 && largeScreen > 0 && xlargeScreen > 0
1909282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    && requiresSmallestWidthDp > 0) {
1910282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                int compatWidth = compatibleWidthLimitDp;
1911282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (compatWidth <= 0) {
1912282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    compatWidth = requiresSmallestWidthDp;
1913282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1914282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (requiresSmallestWidthDp <= 240 && compatWidth >= 240) {
1915282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    smallScreen = -1;
1916282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1917282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    smallScreen = 0;
1918282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1919282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (requiresSmallestWidthDp <= 320 && compatWidth >= 320) {
1920282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    normalScreen = -1;
1921282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1922282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    normalScreen = 0;
1923282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1924282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (requiresSmallestWidthDp <= 480 && compatWidth >= 480) {
1925282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    largeScreen = -1;
1926282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1927282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    largeScreen = 0;
1928282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1929282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (requiresSmallestWidthDp <= 720 && compatWidth >= 720) {
1930282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    xlargeScreen = -1;
1931282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1932282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    xlargeScreen = 0;
1933282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1934282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1935282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1936282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Determine default values for any unspecified screen sizes,
1937282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // based on the target SDK of the package.  As of 4 (donut)
1938282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // the screen size support was introduced, so all default to
1939282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // enabled.
1940282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (smallScreen > 0) {
1941282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                smallScreen = targetSdk >= 4 ? -1 : 0;
1942282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1943282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (normalScreen > 0) {
1944282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                normalScreen = -1;
1945282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1946282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (largeScreen > 0) {
1947282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                largeScreen = targetSdk >= 4 ? -1 : 0;
1948282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1949282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (xlargeScreen > 0) {
1950282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Introduced in Gingerbread.
1951282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                xlargeScreen = targetSdk >= 9 ? -1 : 0;
1952282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1953282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (anyDensity > 0) {
1954282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                anyDensity = (targetSdk >= 4 || requiresSmallestWidthDp > 0
1955282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        || compatibleWidthLimitDp > 0) ? -1 : 0;
1956282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1957282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("supports-screens:");
1958282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (smallScreen != 0) {
1959282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf(" 'small'");
1960282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1961282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (normalScreen != 0) {
1962282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf(" 'normal'");
1963282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1964282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (largeScreen != 0) {
1965282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf(" 'large'");
1966282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1967282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (xlargeScreen != 0) {
1968282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf(" 'xlarge'");
1969282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1970282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("\n");
1971282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("supports-any-density: '%s'\n", anyDensity ? "true" : "false");
1972282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (requiresSmallestWidthDp > 0) {
1973282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("requires-smallest-width:'%d'\n", requiresSmallestWidthDp);
1974282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1975282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (compatibleWidthLimitDp > 0) {
1976282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("compatible-width-limit:'%d'\n", compatibleWidthLimitDp);
1977282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1978282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (largestWidthLimitDp > 0) {
1979282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("largest-width-limit:'%d'\n", largestWidthLimitDp);
1980282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1981282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1982282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("locales:");
1983282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t NL = locales.size();
1984282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t i=0; i<NL; i++) {
1985282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                const char* localeStr =  locales[i].string();
1986282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (localeStr == NULL || strlen(localeStr) == 0) {
1987282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    localeStr = "--_--";
1988282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1989282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf(" '%s'", localeStr);
1990282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1991282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("\n");
1992282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1993282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("densities:");
1994282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t ND = densities.size();
1995282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t i=0; i<ND; i++) {
1996282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf(" '%d'", densities[i]);
1997282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1998282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("\n");
1999282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2000282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            AssetDir* dir = assets.openNonAssetDir(assetsCookie, "lib");
2001282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (dir != NULL) {
2002282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (dir->getFileCount() > 0) {
2003e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                    SortedVector<String8> architectures;
2004282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    for (size_t i=0; i<dir->getFileCount(); i++) {
2005e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        architectures.add(ResTable::normalizeForOutput(
2006e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                                dir->getFileName(i).string()));
2007e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                    }
2008e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski
2009e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                    bool outputAltNativeCode = false;
2010e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                    // A multiArch package is one that contains 64-bit and
2011e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                    // 32-bit versions of native code and expects 3rd-party
2012e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                    // apps to load these native code libraries. Since most
2013e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                    // 64-bit systems also support 32-bit apps, the apps
2014e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                    // loading this multiArch package's code may be either
2015e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                    // 32-bit or 64-bit.
2016e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                    if (hasMultiArch) {
2017e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        // If this is a multiArch package, report the 64-bit
2018e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        // version only. Then as a separate entry, report the
2019e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        // rest.
2020e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        //
2021e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        // If we report the 32-bit architecture, this APK will
2022e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        // be installed on a 32-bit device, causing a large waste
2023e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        // of bandwidth and disk space. This assumes that
2024e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        // the developer of the multiArch package has also
2025e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        // made a version that is 32-bit only.
2026e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        String8 intel64("x86_64");
2027e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        String8 arm64("arm64-v8a");
2028e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        ssize_t index = architectures.indexOf(intel64);
2029e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        if (index < 0) {
2030e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                            index = architectures.indexOf(arm64);
2031e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        }
2032e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski
2033e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        if (index >= 0) {
2034e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                            printf("native-code: '%s'\n", architectures[index].string());
2035e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                            architectures.removeAt(index);
2036e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                            outputAltNativeCode = true;
2037e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        }
2038e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                    }
2039e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski
2040e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                    const size_t archCount = architectures.size();
2041e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                    if (archCount > 0) {
2042e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        if (outputAltNativeCode) {
2043e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                            printf("alt-");
2044e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        }
2045e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        printf("native-code:");
2046e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        for (size_t i = 0; i < archCount; i++) {
2047e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                            printf(" '%s'", architectures[i].string());
2048e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        }
2049e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski                        printf("\n");
2050282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2051282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2052282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                delete dir;
2053282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2054282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else if (strcmp("badger", option) == 0) {
2055282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf("%s", CONSOLE_DATA);
2056282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else if (strcmp("configurations", option) == 0) {
2057282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Vector<ResTable_config> configs;
2058282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            res.getConfigurations(&configs);
2059282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t N = configs.size();
2060282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t i=0; i<N; i++) {
2061282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("%s\n", configs[i].toString().string());
2062282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2063282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
2064282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: unknown dump option '%s'\n", option);
2065282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
2066282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2067282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2068282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2069282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    result = NO_ERROR;
2070282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2071282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail:
2072282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (asset) {
2073282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        delete asset;
2074282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2075282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return (result != NO_ERROR);
2076282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2077282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2078282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2079282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
2080282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Handle the "add" command, which wants to add files to a new or
2081282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * pre-existing archive.
2082282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
2083282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doAdd(Bundle* bundle)
2084282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2085282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ZipFile* zip = NULL;
2086282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t result = UNKNOWN_ERROR;
2087282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char* zipFileName;
2088282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2089282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getUpdate()) {
2090282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        /* avoid confusion */
2091282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: can't use '-u' with add\n");
2092282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2093282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2094282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2095282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getFileSpecCount() < 1) {
2096282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: must specify zip file name\n");
2097282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2098282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2099282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    zipFileName = bundle->getFileSpecEntry(0);
2100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getFileSpecCount() < 2) {
2102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "NOTE: nothing to do\n");
2103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    zip = openReadWrite(zipFileName, true);
2107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (zip == NULL) {
2108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: failed opening/creating '%s' as Zip file\n", zipFileName);
2109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (int i = 1; i < bundle->getFileSpecCount(); i++) {
2113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const char* fileName = bundle->getFileSpecEntry(i);
2114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (strcasecmp(String8(fileName).getPathExtension().string(), ".gz") == 0) {
2116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf(" '%s'... (from gzip)\n", fileName);
2117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            result = zip->addGzip(fileName, String8(fileName).getBasePath().string(), NULL);
2118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
2119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (bundle->getJunkPath()) {
2120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String8 storageName = String8(fileName).getPathLeaf();
21212675f769673f69b0661ddee346292f25cb30a296Maurice Chu                printf(" '%s' as '%s'...\n", fileName,
21222675f769673f69b0661ddee346292f25cb30a296Maurice Chu                        ResTable::normalizeForOutput(storageName.string()).string());
2123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                result = zip->add(fileName, storageName.string(),
2124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  bundle->getCompressionMethod(), NULL);
2125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
2126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf(" '%s'...\n", fileName);
2127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                result = zip->add(fileName, bundle->getCompressionMethod(), NULL);
2128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (result != NO_ERROR) {
2131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "Unable to add '%s' to '%s'", bundle->getFileSpecEntry(i), zipFileName);
2132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (result == NAME_NOT_FOUND) {
2133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, ": file not found\n");
2134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (result == ALREADY_EXISTS) {
2135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, ": already exists in archive\n");
2136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
2137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, "\n");
2138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
2140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    result = NO_ERROR;
2144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail:
2146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    delete zip;
2147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return (result != NO_ERROR);
2148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
2152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Delete files from an existing archive.
2153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
2154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doRemove(Bundle* bundle)
2155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ZipFile* zip = NULL;
2157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t result = UNKNOWN_ERROR;
2158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char* zipFileName;
2159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getFileSpecCount() < 1) {
2161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: must specify zip file name\n");
2162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    zipFileName = bundle->getFileSpecEntry(0);
2165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getFileSpecCount() < 2) {
2167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "NOTE: nothing to do\n");
2168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    zip = openReadWrite(zipFileName, false);
2172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (zip == NULL) {
2173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: failed opening Zip archive '%s'\n",
2174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            zipFileName);
2175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (int i = 1; i < bundle->getFileSpecCount(); i++) {
2179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const char* fileName = bundle->getFileSpecEntry(i);
2180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ZipEntry* entry;
2181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        entry = zip->getEntryByName(fileName);
2183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (entry == NULL) {
2184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            printf(" '%s' NOT FOUND\n", fileName);
2185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
2186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        result = zip->remove(entry);
2189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (result != NO_ERROR) {
2191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "Unable to delete '%s' from '%s'\n",
2192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                bundle->getFileSpecEntry(i), zipFileName);
2193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
2194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /* update the archive */
2198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    zip->flush();
2199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail:
2201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    delete zip;
2202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return (result != NO_ERROR);
2203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
22053921e87e6e67a063caa1987937d7944b24aef489Adam Lesinskistatic status_t addResourcesToBuilder(const sp<AaptDir>& dir, const sp<ApkBuilder>& builder, bool ignoreConfig=false) {
2206fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    const size_t numDirs = dir->getDirs().size();
2207fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    for (size_t i = 0; i < numDirs; i++) {
22083921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski        bool ignore = ignoreConfig;
22093921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski        const sp<AaptDir>& subDir = dir->getDirs().valueAt(i);
22103921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski        const char* dirStr = subDir->getLeaf().string();
22113921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski        if (!ignore && strstr(dirStr, "mipmap") == dirStr) {
22123921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski            ignore = true;
22133921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski        }
22143921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski        status_t err = addResourcesToBuilder(subDir, builder, ignore);
2215fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        if (err != NO_ERROR) {
2216fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            return err;
2217fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        }
2218fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    }
2219fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski
2220fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    const size_t numFiles = dir->getFiles().size();
2221fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    for (size_t i = 0; i < numFiles; i++) {
2222fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        sp<AaptGroup> gp = dir->getFiles().valueAt(i);
2223fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        const size_t numConfigs = gp->getFiles().size();
2224fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        for (size_t j = 0; j < numConfigs; j++) {
22253921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski            status_t err = NO_ERROR;
22263921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski            if (ignoreConfig) {
22273921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski                err = builder->getBaseSplit()->addEntry(gp->getPath(), gp->getFiles().valueAt(j));
22283921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski            } else {
22293921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski                err = builder->addEntry(gp->getPath(), gp->getFiles().valueAt(j));
22303921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski            }
2231fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            if (err != NO_ERROR) {
2232fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                fprintf(stderr, "Failed to add %s (%s) to builder.\n",
2233fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                        gp->getPath().string(), gp->getFiles()[j]->getPrintableSource().string());
2234fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                return err;
2235fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            }
2236fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        }
2237fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    }
2238fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    return NO_ERROR;
2239fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski}
2240fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski
2241fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinskistatic String8 buildApkName(const String8& original, const sp<ApkSplit>& split) {
2242fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (split->isBase()) {
2243fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        return original;
2244fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    }
2245fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski
2246fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    String8 ext(original.getPathExtension());
2247fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (ext == String8(".apk")) {
2248fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        return String8::format("%s_%s%s",
2249fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                original.getBasePath().string(),
2250fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                split->getDirectorySafeName().string(),
2251fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                ext.string());
2252fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    }
2253fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski
2254fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    return String8::format("%s_%s", original.string(),
2255fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            split->getDirectorySafeName().string());
2256fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski}
2257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
2259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Package up an asset directory and associated application files.
2260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
2261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doPackage(Bundle* bundle)
2262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char* outputAPKFile;
2264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int retVal = 1;
2265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err;
2266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<AaptAssets> assets;
2267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int N;
2268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    FILE* fp;
2269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String8 dependencyFile;
2270fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    sp<ApkBuilder> builder;
2271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2272a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin    // -c en_XA or/and ar_XB means do pseudolocalization
2273fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    sp<WeakResourceFilter> configFilter = new WeakResourceFilter();
2274fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    err = configFilter->parse(bundle->getConfigurations());
2275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
2276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2278fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (configFilter->containsPseudo()) {
2279a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        bundle->setPseudolocalize(bundle->getPseudolocalize() | PSEUDO_ACCENTED);
2280a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin    }
2281fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (configFilter->containsPseudoBidi()) {
2282a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        bundle->setPseudolocalize(bundle->getPseudolocalize() | PSEUDO_BIDI);
2283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    N = bundle->getFileSpecCount();
2286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (N < 1 && bundle->getResourceSourceDirs().size() == 0 && bundle->getJarFiles().size() == 0
228709384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski            && bundle->getAndroidManifestFile() == NULL && bundle->getAssetSourceDirs().size() == 0) {
2288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: no input files\n");
2289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    outputAPKFile = bundle->getOutputAPKFile();
2293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Make sure the filenames provided exist and are of the appropriate type.
2295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (outputAPKFile) {
2296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        FileType type;
2297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        type = getFileType(outputAPKFile);
2298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (type != kFileTypeNonexistent && type != kFileTypeRegular) {
2299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr,
2300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                "ERROR: output file '%s' exists but is not regular file\n",
2301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                outputAPKFile);
2302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
2303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Load the assets.
2307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    assets = new AaptAssets();
2308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Set up the resource gathering in assets if we're going to generate
2310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // dependency files. Every time we encounter a resource while slurping
2311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // the tree, we'll add it to these stores so we have full resource paths
2312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // to write to a dependency file.
2313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getGenDependencies()) {
2314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<FilePathStore> resPathStore = new FilePathStore;
2315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        assets->setFullResPaths(resPathStore);
2316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<FilePathStore> assetPathStore = new FilePathStore;
2317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        assets->setFullAssetPaths(assetPathStore);
2318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    err = assets->slurpFromArgs(bundle);
2321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err < 0) {
2322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getVerbose()) {
2326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        assets->print(String8());
2327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2329fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    // Create the ApkBuilder, which will collect the compiled files
2330fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    // to write to the final APK (or sets of APKs if we are building
2331fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    // a Split APK.
2332fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    builder = new ApkBuilder(configFilter);
2333fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski
2334fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    // If we are generating a Split APK, find out which configurations to split on.
2335fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    if (bundle->getSplitConfigurations().size() > 0) {
2336fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        const Vector<String8>& splitStrs = bundle->getSplitConfigurations();
2337fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        const size_t numSplits = splitStrs.size();
2338fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        for (size_t i = 0; i < numSplits; i++) {
2339fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            std::set<ConfigDescription> configs;
2340fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            if (!AaptConfig::parseCommaSeparatedList(splitStrs[i], &configs)) {
2341fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                fprintf(stderr, "ERROR: failed to parse split configuration '%s'\n", splitStrs[i].string());
2342fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                goto bail;
2343fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            }
2344fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski
2345fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            err = builder->createSplitForConfigs(configs);
2346fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            if (err != NO_ERROR) {
2347fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                goto bail;
2348fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            }
2349fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        }
2350fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    }
2351fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski
2352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // If they asked for any fileAs that need to be compiled, do so.
2353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getResourceSourceDirs().size() || bundle->getAndroidManifestFile()) {
2354fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        err = buildResources(bundle, assets, builder);
2355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != 0) {
2356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
2357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // At this point we've read everything and processed everything.  From here
2361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // on out it's just writing output files.
2362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (SourcePos::hasErrors()) {
2363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Update symbols with information about which ones are needed as Java symbols.
2367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    assets->applyJavaSymbols();
2368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (SourcePos::hasErrors()) {
2369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // If we've been asked to generate a dependency file, do that here
2373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getGenDependencies()) {
2374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // If this is the packaging step, generate the dependency file next to
2375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // the output apk (e.g. bin/resources.ap_.d)
2376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (outputAPKFile) {
2377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            dependencyFile = String8(outputAPKFile);
2378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Add the .d extension to the dependency file.
2379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            dependencyFile.append(".d");
2380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
2381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Else if this is the R.java dependency generation step,
2382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // generate the dependency file in the R.java package subdirectory
2383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // e.g. gen/com/foo/app/R.java.d
2384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            dependencyFile = String8(bundle->getRClassDir());
2385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            dependencyFile.appendPath("R.java.d");
2386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Make sure we have a clean dependency file to start with
2388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fp = fopen(dependencyFile, "w");
2389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fclose(fp);
2390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Write out R.java constants
2393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (!assets->havePrivateSymbols()) {
2394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (bundle->getCustomPackage() == NULL) {
2395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Write the R.java file into the appropriate class directory
2396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // e.g. gen/com/foo/app/R.java
23971e466385d4a4f1acee080fa0fdf16cc8fd8ce7caAdam Lesinski            err = writeResourceSymbols(bundle, assets, assets->getPackage(), true,
23981e466385d4a4f1acee080fa0fdf16cc8fd8ce7caAdam Lesinski                    bundle->getBuildSharedLibrary());
2399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
2400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const String8 customPkg(bundle->getCustomPackage());
24011e466385d4a4f1acee080fa0fdf16cc8fd8ce7caAdam Lesinski            err = writeResourceSymbols(bundle, assets, customPkg, true,
24021e466385d4a4f1acee080fa0fdf16cc8fd8ce7caAdam Lesinski                    bundle->getBuildSharedLibrary());
2403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err < 0) {
2405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
2406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // If we have library files, we're going to write our R.java file into
2408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // the appropriate class directory for those libraries as well.
2409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // e.g. gen/com/foo/app/lib/R.java
2410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (bundle->getExtraPackages() != NULL) {
2411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Split on colon
2412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 libs(bundle->getExtraPackages());
2413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            char* packageString = strtok(libs.lockBuffer(libs.length()), ":");
2414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            while (packageString != NULL) {
2415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Write the R.java file out with the correct package name
24160f3a5a6559a955ea20f1ae2d3e0995f3fa821c90Marcin Kosiba                err = writeResourceSymbols(bundle, assets, String8(packageString), true,
24170f3a5a6559a955ea20f1ae2d3e0995f3fa821c90Marcin Kosiba                        bundle->getBuildSharedLibrary());
2418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (err < 0) {
2419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    goto bail;
2420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                packageString = strtok(NULL, ":");
2422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            libs.unlockBuffer();
2424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
24261e466385d4a4f1acee080fa0fdf16cc8fd8ce7caAdam Lesinski        err = writeResourceSymbols(bundle, assets, assets->getPackage(), false, false);
2427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err < 0) {
2428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
2429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
24301e466385d4a4f1acee080fa0fdf16cc8fd8ce7caAdam Lesinski        err = writeResourceSymbols(bundle, assets, assets->getSymbolsPrivatePackage(), true, false);
2431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err < 0) {
2432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
2433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2434282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Write out the ProGuard file
2437282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    err = writeProguardFile(bundle, assets);
2438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err < 0) {
2439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        goto bail;
2440282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2441282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Write the apk
2443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (outputAPKFile) {
2444fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        // Gather all resources and add them to the APK Builder. The builder will then
2445fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        // figure out which Split they belong in.
2446fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        err = addResourcesToBuilder(assets, builder);
2447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != NO_ERROR) {
2448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            goto bail;
2449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2450fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski
2451fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        const Vector<sp<ApkSplit> >& splits = builder->getSplits();
2452fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        const size_t numSplits = splits.size();
2453fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        for (size_t i = 0; i < numSplits; i++) {
2454fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            const sp<ApkSplit>& split = splits[i];
2455fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            String8 outputPath = buildApkName(String8(outputAPKFile), split);
2456fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            err = writeAPK(bundle, outputPath, split);
2457fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            if (err != NO_ERROR) {
2458fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                fprintf(stderr, "ERROR: packaging of '%s' failed\n", outputPath.string());
2459fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                goto bail;
2460fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            }
2461fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        }
2462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // If we've been asked to generate a dependency file, we need to finish up here.
2465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // the writeResourceSymbols and writeAPK functions have already written the target
2466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // half of the dependency file, now we need to write the prerequisites. (files that
2467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // the R.java file or .ap_ file depend on)
2468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getGenDependencies()) {
2469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Now that writeResourceSymbols or writeAPK has taken care of writing
2470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // the targets to our dependency file, we'll write the prereqs
2471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fp = fopen(dependencyFile, "a+");
2472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(fp, " : ");
2473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        bool includeRaw = (outputAPKFile != NULL);
2474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        err = writeDependencyPreReqs(bundle, assets, fp, includeRaw);
2475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Also manually add the AndroidManifeset since it's not under res/ or assets/
2476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // and therefore was not added to our pathstores during slurping
2477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(fp, "%s \\\n", bundle->getAndroidManifestFile());
2478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fclose(fp);
2479282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    retVal = 0;
2482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail:
2483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (SourcePos::hasErrors()) {
2484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        SourcePos::printErrors(stderr);
2485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return retVal;
2487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
2490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Do PNG Crunching
2491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * PRECONDITIONS
2492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *  -S flag points to a source directory containing drawable* folders
2493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *  -C flag points to destination directory. The folder structure in the
2494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *     source directory will be mirrored to the destination (cache) directory
2495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
2496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * POSTCONDITIONS
2497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *  Destination directory will be updated to match the PNG files in
24982675f769673f69b0661ddee346292f25cb30a296Maurice Chu *  the source directory.
2499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
2500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doCrunch(Bundle* bundle)
2501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(stdout, "Crunching PNG Files in ");
2503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(stdout, "source dir: %s\n", bundle->getResourceSourceDirs()[0]);
2504282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(stdout, "To destination dir: %s\n", bundle->getCrunchedOutputDir());
2505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    updatePreProcessedCache(bundle);
2507282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2508282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
2509282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2511282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
2512282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Do PNG Crunching on a single flag
2513282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *  -i points to a single png file
2514282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *  -o points to a single png output file
2515282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
2516282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doSingleCrunch(Bundle* bundle)
2517282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2518282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(stdout, "Crunching single PNG file: %s\n", bundle->getSingleCrunchInputFile());
2519282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(stdout, "\tOutput file: %s\n", bundle->getSingleCrunchOutputFile());
2520282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2521282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String8 input(bundle->getSingleCrunchInputFile());
2522282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String8 output(bundle->getSingleCrunchOutputFile());
2523282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2524282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (preProcessImageToCache(bundle, input, output) != NO_ERROR) {
2525282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // we can't return the status_t as it gets truncate to the lower 8 bits.
2526282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return 42;
2527282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2528282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2529282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
2530282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2531282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
25326f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochezint runInDaemonMode(Bundle* bundle) {
25336f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez    std::cout << "Ready" << std::endl;
2534de3ab0a9e8609f6a631b2c047f352069bb9cfa86Chris Warrington    for (std::string cmd; std::getline(std::cin, cmd);) {
2535de3ab0a9e8609f6a631b2c047f352069bb9cfa86Chris Warrington        if (cmd == "quit") {
25366f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez            return NO_ERROR;
2537de3ab0a9e8609f6a631b2c047f352069bb9cfa86Chris Warrington        } else if (cmd == "s") {
2538de3ab0a9e8609f6a631b2c047f352069bb9cfa86Chris Warrington            // Two argument crunch
2539de3ab0a9e8609f6a631b2c047f352069bb9cfa86Chris Warrington            std::string inputFile, outputFile;
2540de3ab0a9e8609f6a631b2c047f352069bb9cfa86Chris Warrington            std::getline(std::cin, inputFile);
2541de3ab0a9e8609f6a631b2c047f352069bb9cfa86Chris Warrington            std::getline(std::cin, outputFile);
2542de3ab0a9e8609f6a631b2c047f352069bb9cfa86Chris Warrington            bundle->setSingleCrunchInputFile(inputFile.c_str());
2543de3ab0a9e8609f6a631b2c047f352069bb9cfa86Chris Warrington            bundle->setSingleCrunchOutputFile(outputFile.c_str());
2544de3ab0a9e8609f6a631b2c047f352069bb9cfa86Chris Warrington            std::cout << "Crunching " << inputFile << std::endl;
25456f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez            if (doSingleCrunch(bundle) != NO_ERROR) {
25466f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez                std::cout << "Error" << std::endl;
25476f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez            }
25486f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez            std::cout << "Done" << std::endl;
25496f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez        } else {
25506f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez            // in case of invalid command, just bail out.
25516f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez            std::cerr << "Unknown command" << std::endl;
25526f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez            return -1;
25536f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez        }
25546f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez    }
25556f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez    return -1;
25566f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez}
25576f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez
2558282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskichar CONSOLE_DATA[2925] = {
2559282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2560282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 95, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2561282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2562282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32,
2563282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 63,
2564282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    86, 35, 40, 46, 46, 95, 95, 95, 95, 97, 97, 44, 32, 46, 124, 42, 33, 83,
2565282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    62, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2566282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2567282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 46, 58, 59, 61, 59, 61, 81,
2568282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 66, 96, 61, 61, 58, 46, 46, 46, 58, 32, 32, 32, 32, 32, 32,
2569282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32,
2570282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2571282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 46, 61, 59, 59, 59, 58, 106, 81, 81, 81, 81, 102, 59, 61, 59,
2572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 61, 61, 61, 58, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59,
2575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 58, 109, 81, 81, 81, 81, 61, 59, 59, 59, 59, 59, 58, 59, 59, 46, 32,
2576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 60, 81, 81, 81, 81, 87,
2579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    58, 59, 59, 59, 59, 59, 59, 61, 119, 44, 32, 32, 32, 32, 32, 32, 32, 32,
2580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32,
2581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46,
2582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    47, 61, 59, 59, 58, 100, 81, 81, 81, 81, 35, 58, 59, 59, 59, 59, 59, 58,
2583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    121, 81, 91, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 109, 58, 59, 59, 61, 81, 81,
2586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 109, 58, 59, 59, 59, 59, 61, 109, 81, 81, 76, 46, 32, 32, 32,
2587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32,
2588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 41, 87, 59, 61, 59, 41, 81, 81, 81, 81, 81, 81, 59, 61, 59,
2590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 58, 109, 81, 81, 87, 39, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 60, 81, 91, 59,
2593282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 61, 81, 81, 81, 81, 81, 87, 43, 59, 58, 59, 60, 81, 81, 81, 76, 32,
2594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 52, 91, 58, 45, 59, 87, 81, 81, 81, 81,
2597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    70, 58, 58, 58, 59, 106, 81, 81, 81, 91, 32, 32, 32, 32, 32, 32, 32, 32,
2598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32,
2599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 93, 40, 32, 46, 59, 100, 81, 81, 81, 81, 40, 58, 46, 46, 58, 100, 81,
2601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 68, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 46, 46, 46, 32, 46, 46, 46, 32, 46, 32, 46, 45, 91, 59, 61, 58, 109,
2604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 87, 46, 58, 61, 59, 60, 81, 81, 80, 32, 32, 32, 32, 32, 32,
2605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32,
2606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 46, 46, 61, 59, 61, 61, 61, 59, 61, 61, 59,
2607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 58, 58, 46, 46, 41, 58, 59, 58, 81, 81, 81, 81, 69, 58, 59, 59,
2608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    60, 81, 81, 68, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 58, 59,
2610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    61, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 61, 46,
2611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    61, 59, 93, 81, 81, 81, 81, 107, 58, 59, 58, 109, 87, 68, 96, 32, 32, 32,
2612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 10, 32, 32, 32, 46, 60, 61, 61, 59, 59, 59, 59, 59, 59, 59, 59,
2614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 59, 59, 59, 59, 58, 58, 58, 115, 109, 68, 41, 36, 81,
2615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    109, 46, 61, 61, 81, 69, 96, 46, 58, 58, 46, 58, 46, 46, 32, 32, 32, 32,
2616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 46, 32, 95, 81,
2617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    67, 61, 61, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
2618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 58, 68, 39, 61, 105, 61, 63, 81, 119, 58, 106, 80, 32, 58,
2619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    61, 59, 59, 61, 59, 61, 59, 61, 46, 95, 32, 32, 32, 32, 32, 32, 32, 32,
2620282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 10, 32, 32, 36, 81, 109, 105, 59, 61, 59, 59, 59,
2621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 46, 58, 37,
2622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    73, 108, 108, 62, 52, 81, 109, 34, 32, 61, 59, 59, 59, 59, 59, 59, 59, 59,
2623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 61, 59, 61, 61, 46, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10,
2624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 46, 45, 57, 101, 43, 43, 61, 61, 59, 59, 59, 59, 59, 59, 61, 59, 59,
2625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 59, 59, 58, 97, 46, 61, 108, 62, 126, 58, 106, 80, 96,
2626282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    46, 61, 61, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 61,
2627282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    97, 103, 97, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 45, 46, 32,
2628282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    46, 32, 32, 32, 32, 32, 32, 32, 32, 45, 45, 45, 58, 59, 59, 59, 59, 61,
2629282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    119, 81, 97, 124, 105, 124, 124, 39, 126, 95, 119, 58, 61, 58, 59, 59, 59,
2630282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 119, 81, 81, 99, 32, 32,
2631282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2632282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 58, 59, 59, 58, 106, 81, 81, 81, 109, 119,
2633282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    119, 119, 109, 109, 81, 81, 122, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59,
2634282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 58, 115, 81, 87, 81, 102, 32, 32, 32, 32, 32, 32, 10,
2635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 61, 58, 59, 61, 81, 81, 81, 81, 81, 81, 87, 87, 81, 81, 81, 81,
2637282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 58, 59, 59, 59, 59, 59, 59, 59, 59, 58, 45, 45, 45, 59, 59, 59, 41,
2638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    87, 66, 33, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32,
2639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 59, 59, 93, 81,
2640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 40, 58, 59, 59, 59, 58,
2641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    45, 32, 46, 32, 32, 32, 32, 32, 46, 32, 126, 96, 32, 32, 32, 32, 32, 32,
2642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 58, 61, 59, 58, 81, 81, 81, 81, 81, 81, 81, 81,
2644282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 81, 81, 40, 58, 59, 59, 59, 58, 32, 32, 32, 32, 32, 32, 32,
2645282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32,
2646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58,
2647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 58, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 40, 58,
2648282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 46, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 59, 60, 81, 81, 81, 81,
2651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 81, 81, 81, 81, 81, 81, 59, 61, 59, 59, 61, 32, 32, 32, 32,
2652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 58, 59, 59, 93, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
2655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 40, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32,
2657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 58, 106,
2658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 76, 58, 59, 59, 59,
2659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 61, 58, 58, 81, 81, 81, 81, 81, 81, 81, 81,
2662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 81, 81, 87, 58, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32,
2663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32,
2664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    58, 59, 61, 41, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 87, 59,
2666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    61, 58, 59, 59, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 58, 61, 81, 81, 81,
2669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 81, 81, 81, 81, 81, 81, 81, 81, 107, 58, 59, 59, 59, 59, 58, 32, 32,
2670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 58, 59, 59, 58, 51, 81, 81, 81, 81, 81, 81, 81, 81, 81,
2673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    81, 102, 94, 59, 59, 59, 59, 59, 61, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32,
2675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 59,
2676282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 43, 63, 36, 81, 81, 81, 87, 64, 86, 102, 58, 59, 59, 59, 59, 59,
2677282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2679282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 59, 59, 59, 59, 43, 33,
2680282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    58, 126, 126, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 32, 46, 32, 32,
2681282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32,
2682282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46,
2683282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    61, 59, 59, 59, 58, 45, 58, 61, 59, 58, 58, 58, 61, 59, 59, 59, 59, 59,
2684282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 59, 59, 58, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32,
2685282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32,
2686282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 59, 59, 58, 95,
2687282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 45, 61, 59, 61, 59, 59, 59, 59, 59, 59, 59, 45, 58, 59, 59, 59, 59,
2688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    61, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2690282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 58, 61, 59, 59, 59, 59, 59, 61, 59, 61, 46, 46, 32, 45, 45, 45,
2691282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 58, 45, 45, 46, 58, 59, 59, 59, 59, 59, 59, 61, 46, 32, 32, 32, 32,
2692282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32,
2693282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 58, 59, 59, 59, 59,
2694282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 61, 59, 46, 32, 32, 46, 32, 46, 32, 58, 61, 59, 59,
2695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 59, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2696282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 45, 59, 59, 59, 59, 59, 59, 59, 59, 58, 32,
2698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59, 59, 58, 32,
2699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10,
2700282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    46, 61, 59, 59, 59, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 61,
2702282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    46, 61, 59, 59, 59, 59, 59, 59, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2703282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32,
2704282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59,
2705282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 32, 46, 61, 58, 59, 59, 59, 59,
2706282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2707282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2708282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 58, 59, 59, 59, 59, 59, 59, 59, 59, 46, 46, 32, 32, 32,
2709282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59, 59, 45, 32, 32, 32, 32, 32,
2710282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32,
2711282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 32, 45, 61,
2712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 59, 59, 58, 32, 46, 32, 32, 32, 32, 32, 32, 32, 58, 59, 59,
2713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    59, 59, 59, 58, 45, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2714282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 45, 45, 45, 45, 32, 46, 32,
2716282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 45, 61, 59, 58, 45, 45, 32, 32, 32,
2717282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2718282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2719282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2720282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 46, 32, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2721282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10
2722282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski  };
2723