Command.cpp revision 2cb761e3ddb9d68ab430013e9cd15ecaab9fbc62
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// Copyright 2006 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// Android Asset Packaging Tool main entry point.
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "ApkBuilder.h"
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "Bundle.h"
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "Images.h"
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "Main.h"
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "ResourceFilter.h"
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "ResourceTable.h"
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "XMLNode.h"
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Errors.h>
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/KeyedVector.h>
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/List.h>
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Log.h>
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/SortedVector.h>
19788717ca599c714d58b2cb5deea1d37b4a711c07Eino-Ville Talvala#include <utils/threads.h>
2010e09c69d659bf54d6efbe1a3660add7f8a39d6eWu-cheng Li#include <utils/Vector.h>
2110e09c69d659bf54d6efbe1a3660add7f8a39d6eWu-cheng Li
224f8e5ce21df881796d05a1b2117dd8868570a57bEino-Ville Talvala#include <errno.h>
23a696f5d667227365da732481770767dcb330dd23Mathias Agopian#include <fcntl.h>
244c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li
2530771b773393596812b6cfd2a4ddf490c43437aaWu-cheng Liusing namespace android;
26fd6f39e147dc077139a41b9c2a4039fbaa20224eJamie Gennis
274f8e5ce21df881796d05a1b2117dd8868570a57bEino-Ville Talvala/*
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Show version info.  All the cool kids do it.
294f8e5ce21df881796d05a1b2117dd8868570a57bEino-Ville Talvala */
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint doVersion(Bundle* bundle)
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
324f8e5ce21df881796d05a1b2117dd8868570a57bEino-Ville Talvala    if (bundle->getFileSpecCount() != 0) {
334f8e5ce21df881796d05a1b2117dd8868570a57bEino-Ville Talvala        printf("(ignoring extra arguments)\n");
347005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala    }
357005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala    printf("Android Asset Packaging Tool, v0.2\n");
367005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala
377005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala    return 0;
387005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala}
39bde61a5731cdfef76a0691f8bd53b880606f5f6eWu-cheng Li
400a12018e4cd6eaaeaec795f6b2af4499fe3a8bcdAli Utku Selen
41bde61a5731cdfef76a0691f8bd53b880606f5f6eWu-cheng Li/*
42bde61a5731cdfef76a0691f8bd53b880606f5f6eWu-cheng Li * Open the file read only.  The call fails if the file doesn't exist.
43bde61a5731cdfef76a0691f8bd53b880606f5f6eWu-cheng Li *
44bde61a5731cdfef76a0691f8bd53b880606f5f6eWu-cheng Li * Returns NULL on failure.
45bde61a5731cdfef76a0691f8bd53b880606f5f6eWu-cheng Li */
46bde61a5731cdfef76a0691f8bd53b880606f5f6eWu-cheng LiZipFile* openReadOnly(const char* fileName)
47bde61a5731cdfef76a0691f8bd53b880606f5f6eWu-cheng Li{
487d9a8ffd08fa950eb14f8224f6090fe46ab4aa9fIgor Murashkin    ZipFile* zip;
49bde61a5731cdfef76a0691f8bd53b880606f5f6eWu-cheng Li    status_t result;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    zip = new ZipFile;
52bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    result = zip->open(fileName, ZipFile::kOpenReadOnly);
53bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    if (result != NO_ERROR) {
54bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor        if (result == NAME_NOT_FOUND) {
55df4578e8ab7008a7e528d5af2ae761b33cf2bdf4Scott Main            fprintf(stderr, "ERROR: '%s' not found\n", fileName);
56bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor        } else if (result == PERMISSION_DENIED) {
577478ea6848c0059e65a4089b4ec2ff4158520870Wu-cheng Li            fprintf(stderr, "ERROR: '%s' access denied\n", fileName);
58df4578e8ab7008a7e528d5af2ae761b33cf2bdf4Scott Main        } else {
59df4578e8ab7008a7e528d5af2ae761b33cf2bdf4Scott Main            fprintf(stderr, "ERROR: failed opening '%s' as Zip file\n",
60bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                fileName);
617478ea6848c0059e65a4089b4ec2ff4158520870Wu-cheng Li        }
62df4578e8ab7008a7e528d5af2ae761b33cf2bdf4Scott Main        delete zip;
63df4578e8ab7008a7e528d5af2ae761b33cf2bdf4Scott Main        return NULL;
64df4578e8ab7008a7e528d5af2ae761b33cf2bdf4Scott Main    }
65df4578e8ab7008a7e528d5af2ae761b33cf2bdf4Scott Main
66df4578e8ab7008a7e528d5af2ae761b33cf2bdf4Scott Main    return zip;
67bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor}
68bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor
69bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor/*
70341ff13689dfe822b598e626272ac2e80041b482Dan Egnor * Open the file read-write.  The file will be created if it doesn't
71bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor * already exist and "okayToCreate" is set.
72bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor *
73bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor * Returns NULL on failure.
74bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor */
75bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan EgnorZipFile* openReadWrite(const char* fileName, bool okayToCreate)
76bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor{
77bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    ZipFile* zip = NULL;
78bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    status_t result;
79bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    int flags;
80bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor
81bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    flags = ZipFile::kOpenReadWrite;
82bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    if (okayToCreate) {
83bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor        flags |= ZipFile::kOpenCreate;
84bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    }
85bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor
86bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    zip = new ZipFile;
87bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    result = zip->open(fileName, flags);
88bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    if (result != NO_ERROR) {
89bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor        delete zip;
90bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor        zip = NULL;
91bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor        goto bail;
92bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    }
93bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor
94bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnorbail:
95bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    return zip;
96bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor}
97bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor
98bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor
99bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor/*
100bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor * Return a short string describing the compression method.
101bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor */
102bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnorconst char* compressionName(int method)
103bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor{
104bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    if (method == ZipEntry::kCompressStored) {
105bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor        return "Stored";
106bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    } else if (method == ZipEntry::kCompressDeflated) {
107bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor        return "Deflated";
108bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    } else {
109bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor        return "Unknown";
110bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    }
111bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor}
112bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor
113bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor/*
114bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor * Return the percent reduction in size (0% == no compression).
115bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor */
116bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnorint calcPercent(long uncompressedLen, long compressedLen)
117bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor{
118bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    if (!uncompressedLen) {
119bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor        return 0;
120bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    } else {
121bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor        return (int) (100.0 - (compressedLen * 100.0) / uncompressedLen + 0.5);
122341ff13689dfe822b598e626272ac2e80041b482Dan Egnor    }
123bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor}
124bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor
125df4578e8ab7008a7e528d5af2ae761b33cf2bdf4Scott Main/*
126df4578e8ab7008a7e528d5af2ae761b33cf2bdf4Scott Main * Handle the "list" command, which can be a simple file dump or
127df4578e8ab7008a7e528d5af2ae761b33cf2bdf4Scott Main * a verbose listing.
1287478ea6848c0059e65a4089b4ec2ff4158520870Wu-cheng Li *
129df4578e8ab7008a7e528d5af2ae761b33cf2bdf4Scott Main * The verbose listing closely matches the output of the Info-ZIP "unzip"
1306c5c3c392b8abce93fd2d366f12449c713ed0016Joe Fernandez * command.
1316c5c3c392b8abce93fd2d366f12449c713ed0016Joe Fernandez */
1326c5c3c392b8abce93fd2d366f12449c713ed0016Joe Fernandezint doList(Bundle* bundle)
1336c5c3c392b8abce93fd2d366f12449c713ed0016Joe Fernandez{
1346c5c3c392b8abce93fd2d366f12449c713ed0016Joe Fernandez    int result = 1;
1356c5c3c392b8abce93fd2d366f12449c713ed0016Joe Fernandez    ZipFile* zip = NULL;
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const ZipEntry* entry;
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    long totalUncLen, totalCompLen;
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char* zipFileName;
1399b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li
140d2c2929c94bec68741b85f4174e11307fb65157fWu-cheng Li    if (bundle->getFileSpecCount() != 1) {
141da83f4674a564007baac03db062a289c8158d940Benny Wong        fprintf(stderr, "ERROR: specify zip file name (only)\n");
142da83f4674a564007baac03db062a289c8158d940Benny Wong        goto bail;
143da83f4674a564007baac03db062a289c8158d940Benny Wong    }
144da83f4674a564007baac03db062a289c8158d940Benny Wong    zipFileName = bundle->getFileSpecEntry(0);
145da83f4674a564007baac03db062a289c8158d940Benny Wong
146da83f4674a564007baac03db062a289c8158d940Benny Wong    zip = openReadOnly(zipFileName);
147da83f4674a564007baac03db062a289c8158d940Benny Wong    if (zip == NULL) {
148da83f4674a564007baac03db062a289c8158d940Benny Wong        goto bail;
149da83f4674a564007baac03db062a289c8158d940Benny Wong    }
1504c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li
151bb1e275c0e684dd213f124da77110cdd9d6f090cWu-cheng Li    int count, i;
1529d062cfe94dcd24b1d61fc83e5de565cb67965b1Wu-cheng Li
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (bundle->getVerbose()) {
1544838e338129e09a37b8c8ad5e44f85ec5cd3aea1Ashok Bhat        printf("Archive:  %s\n", zipFileName);
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        printf(
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            " Length   Method    Size  Ratio   Offset      Date  Time  CRC-32    Name\n");
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        printf(
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            "--------  ------  ------- -----  -------      ----  ----  ------    ----\n");
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1607005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala
161e8b26e197f7c5e4acbdf8a5cd3f014fbc242c8abDave Sparks    totalUncLen = totalCompLen = 0;
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1639d062cfe94dcd24b1d61fc83e5de565cb67965b1Wu-cheng Li    count = zip->getNumEntries();
1643f4639a6611222ae1ae5493de49213250d292139Wu-cheng Li    for (i = 0; i < count; i++) {
1654c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li        entry = zip->getEntryByIndex(i);
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (bundle->getVerbose()) {
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            char dateBuf[32];
16894927dffce1626898b59579dfc5af53b5de8cef6Andrew Harp            time_t when;
1694c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li
170f05c1d63d16e790ac78c5854bb12374f45d6118eWu-cheng Li            when = entry->getModWhen();
1719b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            strftime(dateBuf, sizeof(dateBuf), "%m-%d-%y %H:%M",
172feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                localtime(&when));
173feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
174feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            printf("%8ld  %-7.7s %7ld %3d%%  %8zd  %s  %08lx  %s\n",
175feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                (long) entry->getUncompressedLen(),
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                compressionName(entry->getCompressionMethod()),
17710e09c69d659bf54d6efbe1a3660add7f8a39d6eWu-cheng Li                (long) entry->getCompressedLen(),
17810e09c69d659bf54d6efbe1a3660add7f8a39d6eWu-cheng Li                calcPercent(entry->getUncompressedLen(),
17910e09c69d659bf54d6efbe1a3660add7f8a39d6eWu-cheng Li                            entry->getCompressedLen()),
18010e09c69d659bf54d6efbe1a3660add7f8a39d6eWu-cheng Li                (size_t) entry->getLFHOffset(),
18110e09c69d659bf54d6efbe1a3660add7f8a39d6eWu-cheng Li                dateBuf,
18210e09c69d659bf54d6efbe1a3660add7f8a39d6eWu-cheng Li                entry->getCRC32(),
18310e09c69d659bf54d6efbe1a3660add7f8a39d6eWu-cheng Li                entry->getFileName());
18410e09c69d659bf54d6efbe1a3660add7f8a39d6eWu-cheng Li        } else {
18510e09c69d659bf54d6efbe1a3660add7f8a39d6eWu-cheng Li            printf("%s\n", entry->getFileName());
18610e09c69d659bf54d6efbe1a3660add7f8a39d6eWu-cheng Li        }
18710e09c69d659bf54d6efbe1a3660add7f8a39d6eWu-cheng Li
18810e09c69d659bf54d6efbe1a3660add7f8a39d6eWu-cheng Li        totalUncLen += entry->getUncompressedLen();
18910e09c69d659bf54d6efbe1a3660add7f8a39d6eWu-cheng Li        totalCompLen += entry->getCompressedLen();
19010e09c69d659bf54d6efbe1a3660add7f8a39d6eWu-cheng Li    }
19110e09c69d659bf54d6efbe1a3660add7f8a39d6eWu-cheng Li
19210e09c69d659bf54d6efbe1a3660add7f8a39d6eWu-cheng Li    if (bundle->getVerbose()) {
1934c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li        printf(
1944c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li        "--------          -------  ---                            -------\n");
195c0c683b3344c67700882f8059e7d18266366daa9Wu-cheng Li        printf("%8ld          %7ld  %2d%%                            %d files\n",
1964c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li            totalUncLen,
1974c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li            totalCompLen,
198c0c683b3344c67700882f8059e7d18266366daa9Wu-cheng Li            calcPercent(totalUncLen, totalCompLen),
1994c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li            zip->getNumEntries());
200c0c683b3344c67700882f8059e7d18266366daa9Wu-cheng Li    }
2014c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li
2024c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li    if (bundle->getAndroidList()) {
203341ff13689dfe822b598e626272ac2e80041b482Dan Egnor        AssetManager assets;
204e25cc656392d8866e163f78b60c7791455d0fb44Chih-Chung Chang        if (!assets.addAssetPath(String8(zipFileName), NULL)) {
205e25cc656392d8866e163f78b60c7791455d0fb44Chih-Chung Chang            fprintf(stderr, "ERROR: list -a failed because assets could not be loaded\n");
206e25cc656392d8866e163f78b60c7791455d0fb44Chih-Chung Chang            goto bail;
207e25cc656392d8866e163f78b60c7791455d0fb44Chih-Chung Chang        }
208341ff13689dfe822b598e626272ac2e80041b482Dan Egnor
209b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang        const ResTable& res = assets.getResources(false);
210b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang        if (&res == NULL) {
2114f8e5ce21df881796d05a1b2117dd8868570a57bEino-Ville Talvala            printf("\nNo resource table found.\n");
2124f8e5ce21df881796d05a1b2117dd8868570a57bEino-Ville Talvala        } else {
2134f8e5ce21df881796d05a1b2117dd8868570a57bEino-Ville Talvala#ifndef HAVE_ANDROID_OS
2144f8e5ce21df881796d05a1b2117dd8868570a57bEino-Ville Talvala            printf("\nResource table:\n");
2154f8e5ce21df881796d05a1b2117dd8868570a57bEino-Ville Talvala            res.print(false);
2164f8e5ce21df881796d05a1b2117dd8868570a57bEino-Ville Talvala#endif
2174f8e5ce21df881796d05a1b2117dd8868570a57bEino-Ville Talvala        }
2184f8e5ce21df881796d05a1b2117dd8868570a57bEino-Ville Talvala
2194f8e5ce21df881796d05a1b2117dd8868570a57bEino-Ville Talvala        Asset* manifestAsset = assets.openNonAsset("AndroidManifest.xml",
2204f8e5ce21df881796d05a1b2117dd8868570a57bEino-Ville Talvala                                                   Asset::ACCESS_BUFFER);
2214f8e5ce21df881796d05a1b2117dd8868570a57bEino-Ville Talvala        if (manifestAsset == NULL) {
2224f8e5ce21df881796d05a1b2117dd8868570a57bEino-Ville Talvala            printf("\nNo AndroidManifest.xml found.\n");
2234f8e5ce21df881796d05a1b2117dd8868570a57bEino-Ville Talvala        } else {
2244f8e5ce21df881796d05a1b2117dd8868570a57bEino-Ville Talvala            printf("\nAndroid manifest:\n");
2254f8e5ce21df881796d05a1b2117dd8868570a57bEino-Ville Talvala            ResXMLTree tree;
226b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang            tree.setTo(manifestAsset->getBuffer(true),
227b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang                       manifestAsset->getLength());
228b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang            printXMLBlock(&tree);
229b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang        }
230b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang        delete manifestAsset;
2317836660f5eb45b7b7e1f5119face65c80e2ade17Wu-cheng Li    }
2327836660f5eb45b7b7e1f5119face65c80e2ade17Wu-cheng Li
2337836660f5eb45b7b7e1f5119face65c80e2ade17Wu-cheng Li    result = 0;
234b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang
2357836660f5eb45b7b7e1f5119face65c80e2ade17Wu-cheng Libail:
2367836660f5eb45b7b7e1f5119face65c80e2ade17Wu-cheng Li    delete zip;
2377836660f5eb45b7b7e1f5119face65c80e2ade17Wu-cheng Li    return result;
2387836660f5eb45b7b7e1f5119face65c80e2ade17Wu-cheng Li}
239b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang
240b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Changstatic ssize_t indexOfAttribute(const ResXMLTree& tree, uint32_t attrRes)
241b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang{
242464cb21e2aaa448072449b82156f18bd64c0e613Joe Fernandez    size_t N = tree.getAttributeCount();
243b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang    for (size_t i=0; i<N; i++) {
244b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang        if (tree.getAttributeNameResID(i) == attrRes) {
2457836660f5eb45b7b7e1f5119face65c80e2ade17Wu-cheng Li            return (ssize_t)i;
246b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang        }
247b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang    }
24832a972c693400db50717435139fa292a63bc937aEino-Ville Talvala    return -1;
249b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang}
25032a972c693400db50717435139fa292a63bc937aEino-Ville Talvala
251b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung ChangString8 getAttribute(const ResXMLTree& tree, const char* ns,
25232a972c693400db50717435139fa292a63bc937aEino-Ville Talvala                            const char* attr, String8* outError)
2532fe6fcaff4bdab45484055d6c18dd96d1b7b7be1Wu-cheng Li{
2542fe6fcaff4bdab45484055d6c18dd96d1b7b7be1Wu-cheng Li    ssize_t idx = tree.indexOfAttribute(ns, attr);
2552fe6fcaff4bdab45484055d6c18dd96d1b7b7be1Wu-cheng Li    if (idx < 0) {
2562fe6fcaff4bdab45484055d6c18dd96d1b7b7be1Wu-cheng Li        return String8();
25732a972c693400db50717435139fa292a63bc937aEino-Ville Talvala    }
258b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang    Res_value value;
259b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang    if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
26069ea4e15e52c456537575d21443ac1efdb03a902Brad Fitzpatrick        if (value.dataType != Res_value::TYPE_STRING) {
26169ea4e15e52c456537575d21443ac1efdb03a902Brad Fitzpatrick            if (outError != NULL) {
26269ea4e15e52c456537575d21443ac1efdb03a902Brad Fitzpatrick                *outError = "attribute is not a string value";
26369ea4e15e52c456537575d21443ac1efdb03a902Brad Fitzpatrick            }
264b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang            return String8();
2657836660f5eb45b7b7e1f5119face65c80e2ade17Wu-cheng Li        }
266f7c6c5ad64c8e5d20e1806cc98b9919334c69614Eino-Ville Talvala    }
267f7c6c5ad64c8e5d20e1806cc98b9919334c69614Eino-Ville Talvala    size_t len;
268f7c6c5ad64c8e5d20e1806cc98b9919334c69614Eino-Ville Talvala    const uint16_t* str = tree.getAttributeStringValue(idx, &len);
269f7c6c5ad64c8e5d20e1806cc98b9919334c69614Eino-Ville Talvala    return str ? String8(str, len) : String8();
270f7c6c5ad64c8e5d20e1806cc98b9919334c69614Eino-Ville Talvala}
271f7c6c5ad64c8e5d20e1806cc98b9919334c69614Eino-Ville Talvala
272f7c6c5ad64c8e5d20e1806cc98b9919334c69614Eino-Ville Talvalastatic String8 getAttribute(const ResXMLTree& tree, uint32_t attrRes, String8* outError)
273f7c6c5ad64c8e5d20e1806cc98b9919334c69614Eino-Ville Talvala{
274f7c6c5ad64c8e5d20e1806cc98b9919334c69614Eino-Ville Talvala    ssize_t idx = indexOfAttribute(tree, attrRes);
275f7c6c5ad64c8e5d20e1806cc98b9919334c69614Eino-Ville Talvala    if (idx < 0) {
276f7c6c5ad64c8e5d20e1806cc98b9919334c69614Eino-Ville Talvala        return String8();
277f7c6c5ad64c8e5d20e1806cc98b9919334c69614Eino-Ville Talvala    }
278f7c6c5ad64c8e5d20e1806cc98b9919334c69614Eino-Ville Talvala    Res_value value;
279f7c6c5ad64c8e5d20e1806cc98b9919334c69614Eino-Ville Talvala    if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
280f7c6c5ad64c8e5d20e1806cc98b9919334c69614Eino-Ville Talvala        if (value.dataType != Res_value::TYPE_STRING) {
281b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang            if (outError != NULL) {
282b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang                *outError = "attribute is not a string value";
283b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang            }
284a1c41e13b521cdd611a8fc46e43b5ae0a2c00238Wu-cheng Li            return String8();
285a1c41e13b521cdd611a8fc46e43b5ae0a2c00238Wu-cheng Li        }
286a1c41e13b521cdd611a8fc46e43b5ae0a2c00238Wu-cheng Li    }
287a1c41e13b521cdd611a8fc46e43b5ae0a2c00238Wu-cheng Li    size_t len;
288bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    const uint16_t* str = tree.getAttributeStringValue(idx, &len);
289bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    return str ? String8(str, len) : String8();
290bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor}
291341ff13689dfe822b598e626272ac2e80041b482Dan Egnor
292341ff13689dfe822b598e626272ac2e80041b482Dan Egnorstatic int32_t getIntegerAttribute(const ResXMLTree& tree, uint32_t attrRes,
293bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor        String8* outError, int32_t defValue = -1)
294bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor{
295bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    ssize_t idx = indexOfAttribute(tree, attrRes);
296bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    if (idx < 0) {
297bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor        return defValue;
298bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    }
299bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    Res_value value;
300bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
301bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor        if (value.dataType < Res_value::TYPE_FIRST_INT
302bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                || value.dataType > Res_value::TYPE_LAST_INT) {
303bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor            if (outError != NULL) {
304341ff13689dfe822b598e626272ac2e80041b482Dan Egnor                *outError = "attribute is not an integer value";
305a48b70fa8ff6363d1e5282be70f6be12bc0688dcWu-cheng Li            }
306bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor            return defValue;
307a1c41e13b521cdd611a8fc46e43b5ae0a2c00238Wu-cheng Li        }
308a1c41e13b521cdd611a8fc46e43b5ae0a2c00238Wu-cheng Li    }
309a1c41e13b521cdd611a8fc46e43b5ae0a2c00238Wu-cheng Li    return value.data;
310facc8ce116bd92f7ba7e8ecb76cbda3953260ef9Wu-cheng Li}
311e25cc656392d8866e163f78b60c7791455d0fb44Chih-Chung Chang
312e25cc656392d8866e163f78b60c7791455d0fb44Chih-Chung Changstatic int32_t getResolvedIntegerAttribute(const ResTable* resTable, const ResXMLTree& tree,
3137bc1b21a5217c3737ae82edd3ff2d901c69a51adWu-cheng Li        uint32_t attrRes, String8* outError, int32_t defValue = -1)
314e25cc656392d8866e163f78b60c7791455d0fb44Chih-Chung Chang{
315e25cc656392d8866e163f78b60c7791455d0fb44Chih-Chung Chang    ssize_t idx = indexOfAttribute(tree, attrRes);
316e25cc656392d8866e163f78b60c7791455d0fb44Chih-Chung Chang    if (idx < 0) {
317a48b70fa8ff6363d1e5282be70f6be12bc0688dcWu-cheng Li        return defValue;
318a48b70fa8ff6363d1e5282be70f6be12bc0688dcWu-cheng Li    }
319a48b70fa8ff6363d1e5282be70f6be12bc0688dcWu-cheng Li    Res_value value;
3207836660f5eb45b7b7e1f5119face65c80e2ade17Wu-cheng Li    if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (value.dataType == Res_value::TYPE_REFERENCE) {
3229b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            resTable->resolveReference(&value, 0);
323a48b70fa8ff6363d1e5282be70f6be12bc0688dcWu-cheng Li        }
324a48b70fa8ff6363d1e5282be70f6be12bc0688dcWu-cheng Li        if (value.dataType < Res_value::TYPE_FIRST_INT
325a48b70fa8ff6363d1e5282be70f6be12bc0688dcWu-cheng Li                || value.dataType > Res_value::TYPE_LAST_INT) {
326a48b70fa8ff6363d1e5282be70f6be12bc0688dcWu-cheng Li            if (outError != NULL) {
327a48b70fa8ff6363d1e5282be70f6be12bc0688dcWu-cheng Li                *outError = "attribute is not an integer value";
3287bc1b21a5217c3737ae82edd3ff2d901c69a51adWu-cheng Li            }
329a48b70fa8ff6363d1e5282be70f6be12bc0688dcWu-cheng Li            return defValue;
330a48b70fa8ff6363d1e5282be70f6be12bc0688dcWu-cheng Li        }
331a48b70fa8ff6363d1e5282be70f6be12bc0688dcWu-cheng Li    }
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return value.data;
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3347bc1b21a5217c3737ae82edd3ff2d901c69a51adWu-cheng Li
335feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkstatic String8 getResolvedAttribute(const ResTable* resTable, const ResXMLTree& tree,
336feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        uint32_t attrRes, String8* outError)
337feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk{
338feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    ssize_t idx = indexOfAttribute(tree, attrRes);
339feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (idx < 0) {
340feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return String8();
341feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
342feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    Res_value value;
343feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
344feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (value.dataType == Res_value::TYPE_STRING) {
345feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            size_t len;
346feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            const uint16_t* str = tree.getAttributeStringValue(idx, &len);
347feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            return str ? String8(str, len) : String8();
348feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
349feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        resTable->resolveReference(&value, 0);
350feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (value.dataType != Res_value::TYPE_STRING) {
351feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (outError != NULL) {
352feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                *outError = "attribute is not a string value";
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return String8();
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
357e8b26e197f7c5e4acbdf8a5cd3f014fbc242c8abDave Sparks    size_t len;
3587005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala    const Res_value* value2 = &value;
3593f4639a6611222ae1ae5493de49213250d292139Wu-cheng Li    const char16_t* str = const_cast<ResTable*>(resTable)->valueToString(value2, 0, NULL, &len);
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return str ? String8(str, len) : String8();
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void getResolvedResourceAttribute(Res_value* value, const ResTable* resTable,
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const ResXMLTree& tree, uint32_t attrRes, String8* outError)
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ssize_t idx = indexOfAttribute(tree, attrRes);
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (idx < 0) {
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (outError != NULL) {
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            *outError = "attribute could not be found";
370788717ca599c714d58b2cb5deea1d37b4a711c07Eino-Ville Talvala        }
371788717ca599c714d58b2cb5deea1d37b4a711c07Eino-Ville Talvala        return;
372feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
373feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (tree.getAttributeValue(idx, value) != NO_ERROR) {
374feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (value->dataType == Res_value::TYPE_REFERENCE) {
375feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            resTable->resolveReference(value, 0);
376feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
377feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        // The attribute was found and was resolved if need be.
378feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return;
379feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
380feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (outError != NULL) {
381feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        *outError = "error getting resolved resource attribute";
382feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
383feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
384feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
385feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkstatic void printResolvedResourceAttribute(const ResTable* resTable, const ResXMLTree& tree,
386feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        uint32_t attrRes, String8 attrLabel, String8* outError)
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3889b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    Res_value value;
3891c04a33c040dfb610952d62da9c93a53c291b2d7Wu-cheng Li    getResolvedResourceAttribute(&value, resTable, tree, attrRes, outError);
3901c04a33c040dfb610952d62da9c93a53c291b2d7Wu-cheng Li    if (*outError != "") {
3911c04a33c040dfb610952d62da9c93a53c291b2d7Wu-cheng Li        *outError = "error print resolved resource attribute";
3921c04a33c040dfb610952d62da9c93a53c291b2d7Wu-cheng Li        return;
3931c04a33c040dfb610952d62da9c93a53c291b2d7Wu-cheng Li    }
3941c04a33c040dfb610952d62da9c93a53c291b2d7Wu-cheng Li    if (value.dataType == Res_value::TYPE_STRING) {
3959b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li        String8 result = getResolvedAttribute(resTable, tree, attrRes, outError);
396e0cc55ac725feec88c77b482d1990221c9a80f74Eino-Ville Talvala        printf("%s='%s'", attrLabel.string(),
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ResTable::normalizeForOutput(result.string()).string());
3989b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    } else if (Res_value::TYPE_FIRST_INT <= value.dataType &&
399feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            value.dataType <= Res_value::TYPE_LAST_INT) {
400788717ca599c714d58b2cb5deea1d37b4a711c07Eino-Ville Talvala        printf("%s='%d'", attrLabel.string(), value.data);
401788717ca599c714d58b2cb5deea1d37b4a711c07Eino-Ville Talvala    } else {
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        printf("%s='0x%x'", attrLabel.string(), (int)value.data);
4039b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    }
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// These are attribute resource constants for the platform, as found
407bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor// in android.R.attr
408bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnorenum {
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    LABEL_ATTR = 0x01010001,
4109b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    ICON_ATTR = 0x01010002,
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NAME_ATTR = 0x01010003,
4124c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li    PERMISSION_ATTR = 0x01010006,
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    EXPORTED_ATTR = 0x01010010,
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    GRANT_URI_PERMISSIONS_ATTR = 0x0101001b,
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    RESOURCE_ATTR = 0x01010025,
416bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    DEBUGGABLE_ATTR = 0x0101000f,
417bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    VALUE_ATTR = 0x01010024,
418bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    VERSION_CODE_ATTR = 0x0101021b,
419bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    VERSION_NAME_ATTR = 0x0101021c,
420bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    SCREEN_ORIENTATION_ATTR = 0x0101001e,
421bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    MIN_SDK_VERSION_ATTR = 0x0101020c,
422bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    MAX_SDK_VERSION_ATTR = 0x01010271,
423bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    REQ_TOUCH_SCREEN_ATTR = 0x01010227,
42442419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li    REQ_KEYBOARD_TYPE_ATTR = 0x01010228,
42542419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li    REQ_HARD_KEYBOARD_ATTR = 0x01010229,
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    REQ_NAVIGATION_ATTR = 0x0101022a,
427bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    REQ_FIVE_WAY_NAV_ATTR = 0x01010232,
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    TARGET_SDK_VERSION_ATTR = 0x01010270,
429bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    TEST_ONLY_ATTR = 0x01010272,
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ANY_DENSITY_ATTR = 0x0101026c,
431bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    GL_ES_VERSION_ATTR = 0x01010281,
4329b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    SMALL_SCREEN_ATTR = 0x01010284,
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NORMAL_SCREEN_ATTR = 0x01010285,
434bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    LARGE_SCREEN_ATTR = 0x01010286,
435bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    XLARGE_SCREEN_ATTR = 0x010102bf,
436bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    REQUIRED_ATTR = 0x0101028e,
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SCREEN_SIZE_ATTR = 0x010102ca,
43853b30912d3e8598c05e47308981971e958e98db2Wu-cheng Li    SCREEN_DENSITY_ATTR = 0x010102cb,
43942419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li    REQUIRES_SMALLEST_WIDTH_DP_ATTR = 0x01010364,
44042419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li    COMPATIBLE_WIDTH_LIMIT_DP_ATTR = 0x01010365,
44142419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li    LARGEST_WIDTH_LIMIT_DP_ATTR = 0x01010366,
44242419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li    PUBLIC_KEY_ATTR = 0x010103a6,
443bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    CATEGORY_ATTR = 0x010103e8,
444bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    BANNER_ATTR = 0x10103f2,
445bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor};
446bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectString8 getComponentName(String8 &pkgName, String8 &componentName) {
448ffe1cf251a4f8469695b8acfa37270684dc1b70cWu-cheng Li    ssize_t idx = componentName.find(".");
4499b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    String8 retStr(pkgName);
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (idx == 0) {
451bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor        retStr += componentName;
452bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    } else if (idx < 0) {
453bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor        retStr += ".";
454bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor        retStr += componentName;
455bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    } else {
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return componentName;
45753b30912d3e8598c05e47308981971e958e98db2Wu-cheng Li    }
45842419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li    return retStr;
45942419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li}
46042419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li
461bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnorstatic void printCompatibleScreens(ResXMLTree& tree, String8* outError) {
462bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    size_t len;
463bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    ResXMLTree::event_code_t code;
464bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    int depth = 0;
465bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    bool first = true;
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    printf("compatible-screens:");
467bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
4689b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li        if (code == ResXMLTree::END_TAG) {
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            depth--;
470bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor            if (depth < 0) {
471fd6f39e147dc077139a41b9c2a4039fbaa20224eJamie Gennis                break;
472fd6f39e147dc077139a41b9c2a4039fbaa20224eJamie Gennis            }
473fd6f39e147dc077139a41b9c2a4039fbaa20224eJamie Gennis            continue;
474fd6f39e147dc077139a41b9c2a4039fbaa20224eJamie Gennis        }
4759b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li        if (code != ResXMLTree::START_TAG) {
476bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor            continue;
477bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor        }
478bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor        depth++;
479bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor        const char16_t* ctag16 = tree.getElementName(&len);
480bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor        if (ctag16 == NULL) {
481bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor            *outError = "failed to get XML element name (bad string pool)";
482bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor            return;
483bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor        }
484bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor        String8 tag(ctag16);
485bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor        if (tag == "screen") {
486bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor            int32_t screenSize = getIntegerAttribute(tree,
487bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                    SCREEN_SIZE_ATTR, NULL, -1);
488bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor            int32_t screenDensity = getIntegerAttribute(tree,
4899b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                    SCREEN_DENSITY_ATTR, NULL, -1);
490bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor            if (screenSize > 0 && screenDensity > 0) {
491bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                if (!first) {
492bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                    printf(",");
493bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                }
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                first = false;
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                printf("'%d/%d'", screenSize, screenDensity);
496b8a10fe45657f2dcc50cae8a06805f8438a6937eWu-cheng Li            }
497feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
498b8a10fe45657f2dcc50cae8a06805f8438a6937eWu-cheng Li    }
499feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    printf("\n");
500b8a10fe45657f2dcc50cae8a06805f8438a6937eWu-cheng Li}
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void printUsesPermission(const String8& name, bool optional=false, int maxSdkVersion=-1) {
503feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    printf("uses-permission: name='%s'", ResTable::normalizeForOutput(name.string()).string());
504feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (maxSdkVersion != -1) {
505feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk         printf(" maxSdkVersion='%d'", maxSdkVersion);
506feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    printf("\n");
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
509fd6f39e147dc077139a41b9c2a4039fbaa20224eJamie Gennis    if (optional) {
510fd6f39e147dc077139a41b9c2a4039fbaa20224eJamie Gennis        printf("optional-permission: name='%s'",
511fd6f39e147dc077139a41b9c2a4039fbaa20224eJamie Gennis                ResTable::normalizeForOutput(name.string()).string());
512fd6f39e147dc077139a41b9c2a4039fbaa20224eJamie Gennis        if (maxSdkVersion != -1) {
513fd6f39e147dc077139a41b9c2a4039fbaa20224eJamie Gennis            printf(" maxSdkVersion='%d'", maxSdkVersion);
514fd6f39e147dc077139a41b9c2a4039fbaa20224eJamie Gennis        }
515fd6f39e147dc077139a41b9c2a4039fbaa20224eJamie Gennis        printf("\n");
516fd6f39e147dc077139a41b9c2a4039fbaa20224eJamie Gennis    }
517fd6f39e147dc077139a41b9c2a4039fbaa20224eJamie Gennis}
518fd6f39e147dc077139a41b9c2a4039fbaa20224eJamie Gennis
519fd6f39e147dc077139a41b9c2a4039fbaa20224eJamie Gennisstatic void printUsesImpliedPermission(const String8& name, const String8& reason) {
520fd6f39e147dc077139a41b9c2a4039fbaa20224eJamie Gennis    printf("uses-implied-permission: name='%s' reason='%s'\n",
521fd6f39e147dc077139a41b9c2a4039fbaa20224eJamie Gennis            ResTable::normalizeForOutput(name.string()).string(),
522fd6f39e147dc077139a41b9c2a4039fbaa20224eJamie Gennis            ResTable::normalizeForOutput(reason.string()).string());
52332a972c693400db50717435139fa292a63bc937aEino-Ville Talvala}
524e309a0fd2e528039b3c1f1372a9a7095bcd852ccEino-Ville Talvala
525e309a0fd2e528039b3c1f1372a9a7095bcd852ccEino-Ville TalvalaVector<String8> getNfcAidCategories(AssetManager& assets, String8 xmlPath, bool offHost,
526e309a0fd2e528039b3c1f1372a9a7095bcd852ccEino-Ville Talvala        String8 *outError = NULL)
527e309a0fd2e528039b3c1f1372a9a7095bcd852ccEino-Ville Talvala{
528e309a0fd2e528039b3c1f1372a9a7095bcd852ccEino-Ville Talvala    Asset* aidAsset = assets.openNonAsset(xmlPath, Asset::ACCESS_BUFFER);
529108708b4873fb05cb029b5bcb29a4e917004ca30Eino-Ville Talvala    if (aidAsset == NULL) {
530108708b4873fb05cb029b5bcb29a4e917004ca30Eino-Ville Talvala        if (outError != NULL) *outError = "xml resource does not exist";
531108708b4873fb05cb029b5bcb29a4e917004ca30Eino-Ville Talvala        return Vector<String8>();
532108708b4873fb05cb029b5bcb29a4e917004ca30Eino-Ville Talvala    }
533108708b4873fb05cb029b5bcb29a4e917004ca30Eino-Ville Talvala
534108708b4873fb05cb029b5bcb29a4e917004ca30Eino-Ville Talvala    const String8 serviceTagName(offHost ? "offhost-apdu-service" : "host-apdu-service");
535108708b4873fb05cb029b5bcb29a4e917004ca30Eino-Ville Talvala
536fd6f39e147dc077139a41b9c2a4039fbaa20224eJamie Gennis    bool withinApduService = false;
537fd6f39e147dc077139a41b9c2a4039fbaa20224eJamie Gennis    Vector<String8> categories;
538fd6f39e147dc077139a41b9c2a4039fbaa20224eJamie Gennis
539fd6f39e147dc077139a41b9c2a4039fbaa20224eJamie Gennis    String8 error;
540fd6f39e147dc077139a41b9c2a4039fbaa20224eJamie Gennis    ResXMLTree tree;
541fd6f39e147dc077139a41b9c2a4039fbaa20224eJamie Gennis    tree.setTo(aidAsset->getBuffer(true), aidAsset->getLength());
542dbc289d6c27968bd05cc547ca73579347c3adc99Glenn Kasten
543fd6f39e147dc077139a41b9c2a4039fbaa20224eJamie Gennis    size_t len;
544fd6f39e147dc077139a41b9c2a4039fbaa20224eJamie Gennis    int depth = 0;
545bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    ResXMLTree::event_code_t code;
546bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
547bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor        if (code == ResXMLTree::END_TAG) {
548bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor            depth--;
549bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor            const char16_t* ctag16 = tree.getElementName(&len);
550bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor            if (ctag16 == NULL) {
551bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                *outError = "failed to get XML element name (bad string pool)";
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return Vector<String8>();
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String8 tag(ctag16);
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
556bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor            if (depth == 0 && tag == serviceTagName) {
557341ff13689dfe822b598e626272ac2e80041b482Dan Egnor                withinApduService = false;
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
559951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala
560951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala        } else if (code == ResXMLTree::START_TAG) {
561951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala            depth++;
562951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala            const char16_t* ctag16 = tree.getElementName(&len);
563951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala            if (ctag16 == NULL) {
564bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                *outError = "failed to get XML element name (bad string pool)";
565a696f5d667227365da732481770767dcb330dd23Mathias Agopian                return Vector<String8>();
566df4578e8ab7008a7e528d5af2ae761b33cf2bdf4Scott Main            }
567da0a56df963353a1f1bd1914fa31f870d982dd5aScott Main            String8 tag(ctag16);
5689b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li
5699b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            if (depth == 1) {
570bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                if (tag == serviceTagName) {
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    withinApduService = true;
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (depth == 2 && withinApduService) {
5749b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                if (tag == "aid-group") {
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    String8 category = getAttribute(tree, CATEGORY_ATTR, &error);
576bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                    if (error != "") {
577c5f94d8a4779050125145396ca83fbc862c7ed6bEino-Ville Talvala                        if (outError != NULL) *outError = error;
578c5f94d8a4779050125145396ca83fbc862c7ed6bEino-Ville Talvala                        return Vector<String8>();
579c5f94d8a4779050125145396ca83fbc862c7ed6bEino-Ville Talvala                    }
580bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor
581bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                    categories.add(category);
582bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                }
583bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor            }
584bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor        }
585bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    }
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    aidAsset->close();
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return categories;
5889b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li}
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
590bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnorstatic void printComponentPresence(const char* componentName) {
591bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    printf("provides-component:'%s'\n", componentName);
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
5934c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li
5944c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li/**
5954c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li * Represents a feature that has been automatically added due to
596664d72e6630522589cc013b25f5c9cdd5d949fa3Chih-yu Huang * a pre-requisite or some other reason.
597664d72e6630522589cc013b25f5c9cdd5d949fa3Chih-yu Huang */
598664d72e6630522589cc013b25f5c9cdd5d949fa3Chih-yu Huangstruct ImpliedFeature {
599664d72e6630522589cc013b25f5c9cdd5d949fa3Chih-yu Huang    /**
600664d72e6630522589cc013b25f5c9cdd5d949fa3Chih-yu Huang     * Name of the implied feature.
601f05c1d63d16e790ac78c5854bb12374f45d6118eWu-cheng Li     */
602f05c1d63d16e790ac78c5854bb12374f45d6118eWu-cheng Li    String8 name;
603f05c1d63d16e790ac78c5854bb12374f45d6118eWu-cheng Li
6049d062cfe94dcd24b1d61fc83e5de565cb67965b1Wu-cheng Li    /**
6054c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li     * List of human-readable reasons for why this feature was implied.
6064c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li     */
6074c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li    SortedVector<String8> reasons;
6089b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li};
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Represents a <feature-group> tag in the AndroidManifest.xml
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstruct FeatureGroup {
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FeatureGroup() : openGLESVersion(-1) {}
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6169b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    /**
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Human readable label
618108708b4873fb05cb029b5bcb29a4e917004ca30Eino-Ville Talvala     */
619bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    String8 label;
620bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor
621108708b4873fb05cb029b5bcb29a4e917004ca30Eino-Ville Talvala    /**
622108708b4873fb05cb029b5bcb29a4e917004ca30Eino-Ville Talvala     * Explicit features defined in the group
623108708b4873fb05cb029b5bcb29a4e917004ca30Eino-Ville Talvala     */
624108708b4873fb05cb029b5bcb29a4e917004ca30Eino-Ville Talvala    KeyedVector<String8, bool> features;
625108708b4873fb05cb029b5bcb29a4e917004ca30Eino-Ville Talvala
626108708b4873fb05cb029b5bcb29a4e917004ca30Eino-Ville Talvala    /**
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * OpenGL ES version required
628bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor     */
629bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    int openGLESVersion;
630108708b4873fb05cb029b5bcb29a4e917004ca30Eino-Ville Talvala};
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void addImpliedFeature(KeyedVector<String8, ImpliedFeature>* impliedFeatures,
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const char* name, const char* reason) {
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String8 name8(name);
63594927dffce1626898b59579dfc5af53b5de8cef6Andrew Harp    ssize_t idx = impliedFeatures->indexOfKey(name8);
6367005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala    if (idx < 0) {
6377005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala        idx = impliedFeatures->add(name8, ImpliedFeature());
6387005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala        impliedFeatures->editValueAt(idx).name = name8;
639a6118c6383c6f5703a576d08586a340fd71d28a4Dave Sparks    }
640a6118c6383c6f5703a576d08586a340fd71d28a4Dave Sparks    impliedFeatures->editValueAt(idx).reasons.add(String8(reason));
64194927dffce1626898b59579dfc5af53b5de8cef6Andrew Harp}
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void printFeatureGroup(const FeatureGroup& grp,
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const KeyedVector<String8, ImpliedFeature>* impliedFeatures = NULL) {
645108708b4873fb05cb029b5bcb29a4e917004ca30Eino-Ville Talvala    printf("feature-group: label='%s'\n", grp.label.string());
646108708b4873fb05cb029b5bcb29a4e917004ca30Eino-Ville Talvala
647108708b4873fb05cb029b5bcb29a4e917004ca30Eino-Ville Talvala    if (grp.openGLESVersion > 0) {
648108708b4873fb05cb029b5bcb29a4e917004ca30Eino-Ville Talvala        printf("  uses-gl-es: '0x%x'\n", grp.openGLESVersion);
649108708b4873fb05cb029b5bcb29a4e917004ca30Eino-Ville Talvala    }
650108708b4873fb05cb029b5bcb29a4e917004ca30Eino-Ville Talvala
651108708b4873fb05cb029b5bcb29a4e917004ca30Eino-Ville Talvala    const size_t numFeatures = grp.features.size();
652108708b4873fb05cb029b5bcb29a4e917004ca30Eino-Ville Talvala    for (size_t i = 0; i < numFeatures; i++) {
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!grp.features[i]) {
654bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor            continue;
655bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor        }
656108708b4873fb05cb029b5bcb29a4e917004ca30Eino-Ville Talvala
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const String8& featureName = grp.features.keyAt(i);
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        printf("  uses-feature: name='%s'\n",
65994927dffce1626898b59579dfc5af53b5de8cef6Andrew Harp                ResTable::normalizeForOutput(featureName.string()).string());
66094927dffce1626898b59579dfc5af53b5de8cef6Andrew Harp    }
66194927dffce1626898b59579dfc5af53b5de8cef6Andrew Harp
6627005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala    const size_t numImpliedFeatures =
6637005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala        (impliedFeatures != NULL) ? impliedFeatures->size() : 0;
6647005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala    for (size_t i = 0; i < numImpliedFeatures; i++) {
66594927dffce1626898b59579dfc5af53b5de8cef6Andrew Harp        const ImpliedFeature& impliedFeature = impliedFeatures->valueAt(i);
66694927dffce1626898b59579dfc5af53b5de8cef6Andrew Harp        if (grp.features.indexOfKey(impliedFeature.name) >= 0) {
66794927dffce1626898b59579dfc5af53b5de8cef6Andrew Harp            // The feature is explicitly set, no need to use implied
66894927dffce1626898b59579dfc5af53b5de8cef6Andrew Harp            // definition.
66994927dffce1626898b59579dfc5af53b5de8cef6Andrew Harp            continue;
67094927dffce1626898b59579dfc5af53b5de8cef6Andrew Harp        }
671108708b4873fb05cb029b5bcb29a4e917004ca30Eino-Ville Talvala
672108708b4873fb05cb029b5bcb29a4e917004ca30Eino-Ville Talvala        String8 printableFeatureName(ResTable::normalizeForOutput(
673bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                    impliedFeature.name.string()));
674108708b4873fb05cb029b5bcb29a4e917004ca30Eino-Ville Talvala        printf("  uses-feature: name='%s'\n", printableFeatureName.string());
675108708b4873fb05cb029b5bcb29a4e917004ca30Eino-Ville Talvala        printf("  uses-implied-feature: name='%s' reason='",
67694927dffce1626898b59579dfc5af53b5de8cef6Andrew Harp                printableFeatureName.string());
677bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor        const size_t numReasons = impliedFeature.reasons.size();
678bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor        for (size_t j = 0; j < numReasons; j++) {
679bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor            printf("%s", impliedFeature.reasons[j].string());
680108708b4873fb05cb029b5bcb29a4e917004ca30Eino-Ville Talvala            if (j + 2 < numReasons) {
68194927dffce1626898b59579dfc5af53b5de8cef6Andrew Harp                printf(", ");
682108708b4873fb05cb029b5bcb29a4e917004ca30Eino-Ville Talvala            } else if (j + 1 < numReasons) {
683bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                printf(", and ");
684108708b4873fb05cb029b5bcb29a4e917004ca30Eino-Ville Talvala            }
685108708b4873fb05cb029b5bcb29a4e917004ca30Eino-Ville Talvala        }
686108708b4873fb05cb029b5bcb29a4e917004ca30Eino-Ville Talvala        printf("'\n");
687108708b4873fb05cb029b5bcb29a4e917004ca30Eino-Ville Talvala    }
688108708b4873fb05cb029b5bcb29a4e917004ca30Eino-Ville Talvala}
689108708b4873fb05cb029b5bcb29a4e917004ca30Eino-Ville Talvala
69094927dffce1626898b59579dfc5af53b5de8cef6Andrew Harpstatic void addParentFeatures(FeatureGroup* grp, const String8& name) {
691bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    if (name == "android.hardware.camera.autofocus" ||
692bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor            name == "android.hardware.camera.flash") {
693bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor        grp->features.add(String8("android.hardware.camera"), true);
694108708b4873fb05cb029b5bcb29a4e917004ca30Eino-Ville Talvala    } else if (name == "android.hardware.location.gps" ||
69594927dffce1626898b59579dfc5af53b5de8cef6Andrew Harp            name == "android.hardware.location.network") {
69694927dffce1626898b59579dfc5af53b5de8cef6Andrew Harp        grp->features.add(String8("android.hardware.location"), true);
69794927dffce1626898b59579dfc5af53b5de8cef6Andrew Harp    } else if (name == "android.hardware.touchscreen.multitouch") {
69894927dffce1626898b59579dfc5af53b5de8cef6Andrew Harp        grp->features.add(String8("android.hardware.touchscreen"), true);
69994927dffce1626898b59579dfc5af53b5de8cef6Andrew Harp    } else if (name == "android.hardware.touchscreen.multitouch.distinct") {
7007005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala        grp->features.add(String8("android.hardware.touchscreen.multitouch"), true);
7017005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala        grp->features.add(String8("android.hardware.touchscreen"), true);
7027005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala    } else if (name == "android.hardware.opengles.aep") {
70394927dffce1626898b59579dfc5af53b5de8cef6Andrew Harp        const int openGLESVersion31 = 0x00030001;
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (openGLESVersion31 > grp->openGLESVersion) {
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            grp->openGLESVersion = openGLESVersion31;
70694927dffce1626898b59579dfc5af53b5de8cef6Andrew Harp        }
7073f4639a6611222ae1ae5493de49213250d292139Wu-cheng Li    }
7083f4639a6611222ae1ae5493de49213250d292139Wu-cheng Li}
709bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor
710bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor/*
711bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor * Handle the "dump" command, to extract select data from an archive.
712bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor */
713bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnorextern char CONSOLE_DATA[2925]; // see EOF
714c10275abd6a494c93a025f683dde104a5d4f2793Wu-cheng Liint doDump(Bundle* bundle)
715951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala{
716951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala    status_t result = UNKNOWN_ERROR;
717951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala
718951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala    if (bundle->getFileSpecCount() < 1) {
719951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala        fprintf(stderr, "ERROR: no dump option specified\n");
720951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala        return 1;
721951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala    }
722951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala
723951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala    if (bundle->getFileSpecCount() < 2) {
724951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala        fprintf(stderr, "ERROR: no dump file specified\n");
725951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala        return 1;
72694927dffce1626898b59579dfc5af53b5de8cef6Andrew Harp    }
727bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor
728e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong    const char* option = bundle->getFileSpecEntry(0);
729bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor    const char* filename = bundle->getFileSpecEntry(1);
730bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor
731e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong    AssetManager assets;
732e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong    int32_t assetsCookie;
733e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong    if (!assets.addAssetPath(String8(filename), &assetsCookie)) {
73494927dffce1626898b59579dfc5af53b5de8cef6Andrew Harp        fprintf(stderr, "ERROR: dump failed because assets could not be loaded\n");
735951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala        return 1;
736951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala    }
7375b9bcda3a26e9b1f9b1eff28a2be8853d69614f0Wu-cheng Li
73894927dffce1626898b59579dfc5af53b5de8cef6Andrew Harp    // Make a dummy config for retrieving resources...  we need to supply
739e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong    // non-default values for some configs so that we can retrieve resources
740e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong    // in the app that don't have a default.  The most important of these is
741e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong    // the API version because key resources like icons will have an implicit
742e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong    // version if they are using newer config types like density.
743e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong    ResTable_config config;
744e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong    memset(&config, 0, sizeof(ResTable_config));
745e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong    config.language[0] = 'e';
746e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong    config.language[1] = 'n';
747e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong    config.country[0] = 'U';
748e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong    config.country[1] = 'S';
749e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong    config.orientation = ResTable_config::ORIENTATION_PORT;
750e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong    config.density = ResTable_config::DENSITY_MEDIUM;
751e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong    config.sdkVersion = 10000; // Very high.
752e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong    config.screenWidthDp = 320;
753e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong    config.screenHeightDp = 480;
754e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong    config.smallestScreenWidthDp = 320;
755e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong    config.screenLayout |= ResTable_config::SCREENSIZE_NORMAL;
756e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong    assets.setConfiguration(config);
757e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong
758e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong    const ResTable& res = assets.getResources(false);
759e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong    if (&res == NULL) {
760e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong        fprintf(stderr, "ERROR: dump failed because no resource table was found\n");
761e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong        return 1;
762e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong    } else if (res.getError() != NO_ERROR) {
763e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong        fprintf(stderr, "ERROR: dump failed because the resource table is invalid/corrupt.\n");
764e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong        return 1;
765e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong    }
76632a972c693400db50717435139fa292a63bc937aEino-Ville Talvala
76732a972c693400db50717435139fa292a63bc937aEino-Ville Talvala    // The dynamicRefTable can be null if there are no resources for this asset cookie.
76832a972c693400db50717435139fa292a63bc937aEino-Ville Talvala    // This fine.
76932a972c693400db50717435139fa292a63bc937aEino-Ville Talvala    const DynamicRefTable* dynamicRefTable = res.getDynamicRefTableForCookie(assetsCookie);
77032a972c693400db50717435139fa292a63bc937aEino-Ville Talvala
77132a972c693400db50717435139fa292a63bc937aEino-Ville Talvala    Asset* asset = NULL;
772e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong
773e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong    if (strcmp("resources", option) == 0) {
774e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong#ifndef HAVE_ANDROID_OS
775e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong        res.print(bundle->getValues());
776e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong#endif
777e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong
778e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong    } else if (strcmp("strings", option) == 0) {
779e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong        const ResStringPool* pool = res.getTableStringBlock(0);
780e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong        printStringPool(pool);
781e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong
782e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong    } else if (strcmp("xmltree", option) == 0) {
783e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong        if (bundle->getFileSpecCount() < 3) {
784e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong            fprintf(stderr, "ERROR: no dump xmltree resource file specified\n");
785e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong            goto bail;
786e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong        }
787e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong
788e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong        for (int i=2; i<bundle->getFileSpecCount(); i++) {
789e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong            const char* resname = bundle->getFileSpecEntry(i);
790e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong            ResXMLTree tree(dynamicRefTable);
791e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong            asset = assets.openNonAsset(assetsCookie, resname, Asset::ACCESS_BUFFER);
792e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong            if (asset == NULL) {
793e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong                fprintf(stderr, "ERROR: dump failed because resource %s found\n", resname);
794e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong                goto bail;
795e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong            }
796e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong
797e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong            if (tree.setTo(asset->getBuffer(true),
798e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong                           asset->getLength()) != NO_ERROR) {
799e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong                fprintf(stderr, "ERROR: Resource %s is corrupt\n", resname);
800e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong                goto bail;
8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8027005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            tree.restart();
8037005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            printXMLBlock(&tree);
8047005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            tree.uninit();
8057005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            delete asset;
8067005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            asset = NULL;
8077005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala        }
8087005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala
8097005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala    } else if (strcmp("xmlstrings", option) == 0) {
8107005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala        if (bundle->getFileSpecCount() < 3) {
8117005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            fprintf(stderr, "ERROR: no dump xmltree resource file specified\n");
8127005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            goto bail;
8137005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala        }
8147005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala
8157005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala        for (int i=2; i<bundle->getFileSpecCount(); i++) {
8167005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            const char* resname = bundle->getFileSpecEntry(i);
8177005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            asset = assets.openNonAsset(assetsCookie, resname, Asset::ACCESS_BUFFER);
8187005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            if (asset == NULL) {
8197005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                fprintf(stderr, "ERROR: dump failed because resource %s found\n", resname);
8207005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                goto bail;
8217005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            }
8227005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala
8237005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            ResXMLTree tree(dynamicRefTable);
8247005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            if (tree.setTo(asset->getBuffer(true),
8257005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                           asset->getLength()) != NO_ERROR) {
8267005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                fprintf(stderr, "ERROR: Resource %s is corrupt\n", resname);
8277005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                goto bail;
8287005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            }
8297005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            printStringPool(&tree.getStrings());
8307005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            delete asset;
8317005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            asset = NULL;
8327005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala        }
8337005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala
8347005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala    } else {
8357005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala        asset = assets.openNonAsset(assetsCookie, "AndroidManifest.xml", Asset::ACCESS_BUFFER);
8367005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala        if (asset == NULL) {
8377005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            fprintf(stderr, "ERROR: dump failed because no AndroidManifest.xml found\n");
8387005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            goto bail;
8397005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala        }
8407005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala
8417005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala        ResXMLTree tree(dynamicRefTable);
8427005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala        if (tree.setTo(asset->getBuffer(true),
8437005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                       asset->getLength()) != NO_ERROR) {
8447005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            fprintf(stderr, "ERROR: AndroidManifest.xml is corrupt\n");
8457005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            goto bail;
8467005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala        }
8477005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala        tree.restart();
8487005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala
8497005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala        if (strcmp("permissions", option) == 0) {
8507005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            size_t len;
8517005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            ResXMLTree::event_code_t code;
8527005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            int depth = 0;
8537005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
8547005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                if (code == ResXMLTree::END_TAG) {
8557005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                    depth--;
8567005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                    continue;
8577005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                }
8587005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                if (code != ResXMLTree::START_TAG) {
8597005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                    continue;
8607005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                }
8617005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                depth++;
8627005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                const char16_t* ctag16 = tree.getElementName(&len);
8637005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                if (ctag16 == NULL) {
8647005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                    fprintf(stderr, "ERROR: failed to get XML element name (bad string pool)\n");
8657005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                    goto bail;
8667005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                }
8677005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                String8 tag(ctag16);
8687005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                //printf("Depth %d tag %s\n", depth, tag.string());
8697005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                if (depth == 1) {
8707005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                    if (tag != "manifest") {
8717005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                        fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n");
8727005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                        goto bail;
8737005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                    }
8747005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                    String8 pkg = getAttribute(tree, NULL, "package", NULL);
8757005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                    printf("package: %s\n", ResTable::normalizeForOutput(pkg.string()).string());
8767005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                } else if (depth == 2 && tag == "permission") {
8777005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                    String8 error;
8787005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                    String8 name = getAttribute(tree, NAME_ATTR, &error);
8797005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                    if (error != "") {
8807005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                        fprintf(stderr, "ERROR: %s\n", error.string());
8817005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                        goto bail;
8827005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                    }
8837005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                    printf("permission: %s\n",
8847005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                            ResTable::normalizeForOutput(name.string()).string());
8857005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                } else if (depth == 2 && tag == "uses-permission") {
8867005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                    String8 error;
8877005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                    String8 name = getAttribute(tree, NAME_ATTR, &error);
8887005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                    if (error != "") {
8897005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                        fprintf(stderr, "ERROR: %s\n", error.string());
8907005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                        goto bail;
8917005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                    }
8927005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                    printUsesPermission(name,
8937005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                            getIntegerAttribute(tree, REQUIRED_ATTR, NULL, 1) == 0,
8947005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                            getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR, NULL, -1));
8957005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                }
8967005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            }
8977005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala        } else if (strcmp("badging", option) == 0) {
8987005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            Vector<String8> locales;
8997005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            res.getLocales(&locales);
9007005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala
9017005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            Vector<ResTable_config> configs;
9027005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            res.getConfigurations(&configs);
9037005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            SortedVector<int> densities;
9047005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            const size_t NC = configs.size();
9057005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            for (size_t i=0; i<NC; i++) {
9067005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                int dens = configs[i].density;
9077005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                if (dens == 0) {
9087005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                    dens = 160;
9097005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                }
9107005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                densities.add(dens);
9117005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            }
9127005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala
9137005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            size_t len;
9147005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            ResXMLTree::event_code_t code;
9157005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            int depth = 0;
9167005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            String8 error;
9177005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            bool withinActivity = false;
9187005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            bool isMainActivity = false;
9197005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            bool isLauncherActivity = false;
9207005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            bool isLeanbackLauncherActivity = false;
9217005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            bool isSearchable = false;
9227005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            bool withinApplication = false;
9237005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            bool withinSupportsInput = false;
9247005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            bool withinFeatureGroup = false;
9257005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            bool withinReceiver = false;
9267005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            bool withinService = false;
9277005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            bool withinProvider = false;
9287005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            bool withinIntentFilter = false;
9297005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala            bool hasMainActivity = false;
9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bool hasOtherActivities = false;
9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bool hasOtherReceivers = false;
9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bool hasOtherServices = false;
9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bool hasIntentFilter = false;
9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bool hasWallpaperService = false;
9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bool hasImeService = false;
9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bool hasAccessibilityService = false;
9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bool hasPrintService = false;
9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bool hasWidgetReceivers = false;
9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bool hasDeviceAdminReceiver = false;
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bool hasPaymentService = false;
942c62f9bd13327937aa2d2f20b44215397120634c1Dave Sparks            bool hasDocumentsProvider = false;
9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bool hasCameraActivity = false;
9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bool hasCameraSecureActivity = false;
9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bool hasLauncher = false;
9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bool hasNotificationListenerService = false;
947c62f9bd13327937aa2d2f20b44215397120634c1Dave Sparks            bool hasDreamService = false;
948c62f9bd13327937aa2d2f20b44215397120634c1Dave Sparks
949e8b26e197f7c5e4acbdf8a5cd3f014fbc242c8abDave Sparks            bool actMainActivity = false;
9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bool actWidgetReceivers = false;
951e8b26e197f7c5e4acbdf8a5cd3f014fbc242c8abDave Sparks            bool actDeviceAdminEnabled = false;
9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bool actImeService = false;
9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bool actWallpaperService = false;
954c62f9bd13327937aa2d2f20b44215397120634c1Dave Sparks            bool actAccessibilityService = false;
955e8b26e197f7c5e4acbdf8a5cd3f014fbc242c8abDave Sparks            bool actPrintService = false;
9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bool actHostApduService = false;
957e8b26e197f7c5e4acbdf8a5cd3f014fbc242c8abDave Sparks            bool actOffHostApduService = false;
9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bool actDocumentsProvider = false;
9599b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            bool actNotificationListenerService = false;
960c62f9bd13327937aa2d2f20b44215397120634c1Dave Sparks            bool actDreamService = false;
961ca367b717806c4c69190641c3361d3520a44ad08Eino-Ville Talvala            bool actCamera = false;
962ca367b717806c4c69190641c3361d3520a44ad08Eino-Ville Talvala            bool actCameraSecure = false;
9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bool catLauncher = false;
964a6118c6383c6f5703a576d08586a340fd71d28a4Dave Sparks            bool hasMetaHostPaymentCategory = false;
965a6118c6383c6f5703a576d08586a340fd71d28a4Dave Sparks            bool hasMetaOffHostPaymentCategory = false;
966a6118c6383c6f5703a576d08586a340fd71d28a4Dave Sparks
9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // These permissions are required by services implementing services
96894927dffce1626898b59579dfc5af53b5de8cef6Andrew Harp            // the system binds to (IME, Accessibility, PrintServices, etc.)
969a6118c6383c6f5703a576d08586a340fd71d28a4Dave Sparks            bool hasBindDeviceAdminPermission = false;
970a6118c6383c6f5703a576d08586a340fd71d28a4Dave Sparks            bool hasBindInputMethodPermission = false;
971a6118c6383c6f5703a576d08586a340fd71d28a4Dave Sparks            bool hasBindAccessibilityServicePermission = false;
97294927dffce1626898b59579dfc5af53b5de8cef6Andrew Harp            bool hasBindPrintServicePermission = false;
9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bool hasBindNfcServicePermission = false;
974ca367b717806c4c69190641c3361d3520a44ad08Eino-Ville Talvala            bool hasRequiredSafAttributes = false;
9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bool hasBindNotificationListenerServicePermission = false;
9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bool hasBindDreamServicePermission = false;
9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
978e8b26e197f7c5e4acbdf8a5cd3f014fbc242c8abDave Sparks            // These two implement the implicit permissions that are granted
979e8b26e197f7c5e4acbdf8a5cd3f014fbc242c8abDave Sparks            // to pre-1.6 applications.
980e8b26e197f7c5e4acbdf8a5cd3f014fbc242c8abDave Sparks            bool hasWriteExternalStoragePermission = false;
981e8b26e197f7c5e4acbdf8a5cd3f014fbc242c8abDave Sparks            bool hasReadPhoneStatePermission = false;
982e8b26e197f7c5e4acbdf8a5cd3f014fbc242c8abDave Sparks
983e8b26e197f7c5e4acbdf8a5cd3f014fbc242c8abDave Sparks            // If an app requests write storage, they will also get read storage.
984c62f9bd13327937aa2d2f20b44215397120634c1Dave Sparks            bool hasReadExternalStoragePermission = false;
985f05c1d63d16e790ac78c5854bb12374f45d6118eWu-cheng Li
986f05c1d63d16e790ac78c5854bb12374f45d6118eWu-cheng Li            // Implement transition to read and write call log.
987f05c1d63d16e790ac78c5854bb12374f45d6118eWu-cheng Li            bool hasReadContactsPermission = false;
988f05c1d63d16e790ac78c5854bb12374f45d6118eWu-cheng Li            bool hasWriteContactsPermission = false;
989f05c1d63d16e790ac78c5854bb12374f45d6118eWu-cheng Li            bool hasReadCallLogPermission = false;
990f05c1d63d16e790ac78c5854bb12374f45d6118eWu-cheng Li            bool hasWriteCallLogPermission = false;
991f05c1d63d16e790ac78c5854bb12374f45d6118eWu-cheng Li
992e8b26e197f7c5e4acbdf8a5cd3f014fbc242c8abDave Sparks            // This next group of variables is used to implement a group of
993e8b26e197f7c5e4acbdf8a5cd3f014fbc242c8abDave Sparks            // backward-compatibility heuristics necessitated by the addition of
994e8b26e197f7c5e4acbdf8a5cd3f014fbc242c8abDave Sparks            // some new uses-feature constants in 2.1 and 2.2. In most cases, the
995e8b26e197f7c5e4acbdf8a5cd3f014fbc242c8abDave Sparks            // heuristic is "if an app requests a permission but doesn't explicitly
9963f4639a6611222ae1ae5493de49213250d292139Wu-cheng Li            // request the corresponding <uses-feature>, presume it's there anyway".
9973f4639a6611222ae1ae5493de49213250d292139Wu-cheng Li
998e8b26e197f7c5e4acbdf8a5cd3f014fbc242c8abDave Sparks            // 2.2 also added some other features that apps can request, but that
9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // have no corresponding permission, so we cannot implement any
10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // back-compatibility heuristic for them. The below are thus unnecessary
1001bb1e275c0e684dd213f124da77110cdd9d6f090cWu-cheng Li            // (but are retained here for documentary purposes.)
10024c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li            //bool specCompassFeature = false;
1003f0d6a48c6ad852b84687127f14b1ffde02416dc4Wu-cheng Li            //bool specAccelerometerFeature = false;
10044c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li            //bool specProximityFeature = false;
10054c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li            //bool specAmbientLightFeature = false;
10064c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li            //bool specLiveWallpaperFeature = false;
1007c62f9bd13327937aa2d2f20b44215397120634c1Dave Sparks
10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int targetSdk = 0;
1009e8b26e197f7c5e4acbdf8a5cd3f014fbc242c8abDave Sparks            int smallScreen = 1;
10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int normalScreen = 1;
1011e8b26e197f7c5e4acbdf8a5cd3f014fbc242c8abDave Sparks            int largeScreen = 1;
10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int xlargeScreen = 1;
10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int anyDensity = 1;
10149d062cfe94dcd24b1d61fc83e5de565cb67965b1Wu-cheng Li            int requiresSmallestWidthDp = 0;
10159d062cfe94dcd24b1d61fc83e5de565cb67965b1Wu-cheng Li            int compatibleWidthLimitDp = 0;
10169d062cfe94dcd24b1d61fc83e5de565cb67965b1Wu-cheng Li            int largestWidthLimitDp = 0;
10179d062cfe94dcd24b1d61fc83e5de565cb67965b1Wu-cheng Li            String8 pkg;
10189d062cfe94dcd24b1d61fc83e5de565cb67965b1Wu-cheng Li            String8 activityName;
10199d062cfe94dcd24b1d61fc83e5de565cb67965b1Wu-cheng Li            String8 activityLabel;
10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String8 activityIcon;
10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String8 activityBanner;
10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String8 receiverName;
10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String8 serviceName;
10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Vector<String8> supportedInput;
10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            FeatureGroup commonFeatures;
10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Vector<FeatureGroup> featureGroups;
10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            KeyedVector<String8, ImpliedFeature> impliedFeatures;
10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (code == ResXMLTree::END_TAG) {
10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    depth--;
10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (depth < 2) {
10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (withinSupportsInput && !supportedInput.isEmpty()) {
10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            printf("supports-input: '");
10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            const size_t N = supportedInput.size();
10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            for (size_t i=0; i<N; i++) {
10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                printf("%s", ResTable::normalizeForOutput(
10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                        supportedInput[i].string()).string());
10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                if (i != N - 1) {
1041bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                                    printf("' '");
1042bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                                } else {
10437478ea6848c0059e65a4089b4ec2ff4158520870Wu-cheng Li                                    printf("'\n");
10447478ea6848c0059e65a4089b4ec2ff4158520870Wu-cheng Li                                }
1045df4578e8ab7008a7e528d5af2ae761b33cf2bdf4Scott Main                            }
1046df4578e8ab7008a7e528d5af2ae761b33cf2bdf4Scott Main                            supportedInput.clear();
10477478ea6848c0059e65a4089b4ec2ff4158520870Wu-cheng Li                        }
1048df4578e8ab7008a7e528d5af2ae761b33cf2bdf4Scott Main                        withinApplication = false;
1049df4578e8ab7008a7e528d5af2ae761b33cf2bdf4Scott Main                        withinSupportsInput = false;
1050bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                        withinFeatureGroup = false;
1051bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                    } else if (depth < 3) {
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (withinActivity && isMainActivity) {
10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            String8 aName(getComponentName(pkg, activityName));
10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (isLauncherActivity) {
10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                printf("launchable-activity:");
105669ea4e15e52c456537575d21443ac1efdb03a902Brad Fitzpatrick                                if (aName.length() > 0) {
105769ea4e15e52c456537575d21443ac1efdb03a902Brad Fitzpatrick                                    printf(" name='%s' ",
105869ea4e15e52c456537575d21443ac1efdb03a902Brad Fitzpatrick                                            ResTable::normalizeForOutput(aName.string()).string());
105969ea4e15e52c456537575d21443ac1efdb03a902Brad Fitzpatrick                                }
10609b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                                printf(" label='%s' icon='%s'\n",
1061b4f95be03e018df825356fe2cd363797c66303f1Wu-cheng Li                                        ResTable::normalizeForOutput(activityLabel.string()).string(),
1062b4f95be03e018df825356fe2cd363797c66303f1Wu-cheng Li                                        ResTable::normalizeForOutput(activityIcon.string()).string());
106383d3352cf7a67efd60732c0d40e5928f642f6808Eino-Ville Talvala                            }
10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (isLeanbackLauncherActivity) {
10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                printf("leanback-launchable-activity:");
106683d3352cf7a67efd60732c0d40e5928f642f6808Eino-Ville Talvala                                if (aName.length() > 0) {
106783d3352cf7a67efd60732c0d40e5928f642f6808Eino-Ville Talvala                                    printf(" name='%s' ",
10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                            ResTable::normalizeForOutput(aName.string()).string());
10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                }
107053b30912d3e8598c05e47308981971e958e98db2Wu-cheng Li                                printf(" label='%s' icon='%s' banner='%s'\n",
10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                        ResTable::normalizeForOutput(activityLabel.string()).string(),
10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                        ResTable::normalizeForOutput(activityIcon.string()).string(),
1073bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                                        ResTable::normalizeForOutput(activityBanner.string()).string());
1074bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                            }
1075bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                        }
1076bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                        if (!hasIntentFilter) {
1077bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                            hasOtherActivities |= withinActivity;
1078bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                            hasOtherReceivers |= withinReceiver;
1079bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                            hasOtherServices |= withinService;
1080bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                        } else {
108136322db5752c7ec196f59ba94abe5d5a63cc19f5Wu-cheng Li                            if (withinService) {
1082bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                                hasPaymentService |= (actHostApduService && hasMetaHostPaymentCategory &&
1083da0a56df963353a1f1bd1914fa31f870d982dd5aScott Main                                        hasBindNfcServicePermission);
10847478ea6848c0059e65a4089b4ec2ff4158520870Wu-cheng Li                                hasPaymentService |= (actOffHostApduService && hasMetaOffHostPaymentCategory &&
10857478ea6848c0059e65a4089b4ec2ff4158520870Wu-cheng Li                                        hasBindNfcServicePermission);
1086df4578e8ab7008a7e528d5af2ae761b33cf2bdf4Scott Main                            }
1087df4578e8ab7008a7e528d5af2ae761b33cf2bdf4Scott Main                        }
1088bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                        withinActivity = false;
1089068ef42c3ffe1eccec10f97f08541304f679fe67Wu-cheng Li                        withinService = false;
1090068ef42c3ffe1eccec10f97f08541304f679fe67Wu-cheng Li                        withinReceiver = false;
1091bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                        withinProvider = false;
10927478ea6848c0059e65a4089b4ec2ff4158520870Wu-cheng Li                        hasIntentFilter = false;
109353b30912d3e8598c05e47308981971e958e98db2Wu-cheng Li                        isMainActivity = isLauncherActivity = isLeanbackLauncherActivity = false;
1094b4f95be03e018df825356fe2cd363797c66303f1Wu-cheng Li                    } else if (depth < 4) {
1095b4f95be03e018df825356fe2cd363797c66303f1Wu-cheng Li                        if (withinIntentFilter) {
1096b4f95be03e018df825356fe2cd363797c66303f1Wu-cheng Li                            if (withinActivity) {
109783d3352cf7a67efd60732c0d40e5928f642f6808Eino-Ville Talvala                                hasMainActivity |= actMainActivity;
109853b30912d3e8598c05e47308981971e958e98db2Wu-cheng Li                                hasLauncher |= catLauncher;
109953b30912d3e8598c05e47308981971e958e98db2Wu-cheng Li                                hasCameraActivity |= actCamera;
110053b30912d3e8598c05e47308981971e958e98db2Wu-cheng Li                                hasCameraSecureActivity |= actCameraSecure;
110153b30912d3e8598c05e47308981971e958e98db2Wu-cheng Li                                hasOtherActivities |= !actMainActivity && !actCamera && !actCameraSecure;
110253b30912d3e8598c05e47308981971e958e98db2Wu-cheng Li                            } else if (withinReceiver) {
110353b30912d3e8598c05e47308981971e958e98db2Wu-cheng Li                                hasWidgetReceivers |= actWidgetReceivers;
1104108708b4873fb05cb029b5bcb29a4e917004ca30Eino-Ville Talvala                                hasDeviceAdminReceiver |= (actDeviceAdminEnabled &&
1105108708b4873fb05cb029b5bcb29a4e917004ca30Eino-Ville Talvala                                        hasBindDeviceAdminPermission);
1106108708b4873fb05cb029b5bcb29a4e917004ca30Eino-Ville Talvala                                hasOtherReceivers |= (!actWidgetReceivers && !actDeviceAdminEnabled);
1107108708b4873fb05cb029b5bcb29a4e917004ca30Eino-Ville Talvala                            } else if (withinService) {
11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                hasImeService |= actImeService;
1109bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                                hasWallpaperService |= actWallpaperService;
111083d3352cf7a67efd60732c0d40e5928f642f6808Eino-Ville Talvala                                hasAccessibilityService |= (actAccessibilityService &&
111183d3352cf7a67efd60732c0d40e5928f642f6808Eino-Ville Talvala                                        hasBindAccessibilityServicePermission);
1112108708b4873fb05cb029b5bcb29a4e917004ca30Eino-Ville Talvala                                hasPrintService |= (actPrintService && hasBindPrintServicePermission);
11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                hasNotificationListenerService |= actNotificationListenerService &&
11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                        hasBindNotificationListenerServicePermission;
11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                hasDreamService |= actDreamService && hasBindDreamServicePermission;
1116f05c1d63d16e790ac78c5854bb12374f45d6118eWu-cheng Li                                hasOtherServices |= (!actImeService && !actWallpaperService &&
1117248ba23ad28c1f8fb69904663204df08c5818700James Dong                                        !actAccessibilityService && !actPrintService &&
1118248ba23ad28c1f8fb69904663204df08c5818700James Dong                                        !actHostApduService && !actOffHostApduService &&
1119f05c1d63d16e790ac78c5854bb12374f45d6118eWu-cheng Li                                        !actNotificationListenerService);
11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            } else if (withinProvider) {
11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                hasDocumentsProvider |= actDocumentsProvider && hasRequiredSafAttributes;
11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
1124bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                        withinIntentFilter = false;
1125bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                    }
1126bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                    continue;
1127244f8c26365a303d9dd861bd48a29a4b48578da1Chih-Chung Chang                }
1128bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                if (code != ResXMLTree::START_TAG) {
1129bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                    continue;
1130244f8c26365a303d9dd861bd48a29a4b48578da1Chih-Chung Chang                }
1131244f8c26365a303d9dd861bd48a29a4b48578da1Chih-Chung Chang                depth++;
1132244f8c26365a303d9dd861bd48a29a4b48578da1Chih-Chung Chang
1133f05c1d63d16e790ac78c5854bb12374f45d6118eWu-cheng Li                const char16_t* ctag16 = tree.getElementName(&len);
1134248ba23ad28c1f8fb69904663204df08c5818700James Dong                if (ctag16 == NULL) {
1135248ba23ad28c1f8fb69904663204df08c5818700James Dong                    fprintf(stderr, "ERROR: failed to get XML element name (bad string pool)\n");
1136f05c1d63d16e790ac78c5854bb12374f45d6118eWu-cheng Li                    goto bail;
1137f05c1d63d16e790ac78c5854bb12374f45d6118eWu-cheng Li                }
1138f05c1d63d16e790ac78c5854bb12374f45d6118eWu-cheng Li                String8 tag(ctag16);
1139f05c1d63d16e790ac78c5854bb12374f45d6118eWu-cheng Li                //printf("Depth %d,  %s\n", depth, tag.string());
1140f05c1d63d16e790ac78c5854bb12374f45d6118eWu-cheng Li                if (depth == 1) {
1141f05c1d63d16e790ac78c5854bb12374f45d6118eWu-cheng Li                    if (tag != "manifest") {
1142f05c1d63d16e790ac78c5854bb12374f45d6118eWu-cheng Li                        fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n");
1143f05c1d63d16e790ac78c5854bb12374f45d6118eWu-cheng Li                        goto bail;
1144f05c1d63d16e790ac78c5854bb12374f45d6118eWu-cheng Li                    }
1145f05c1d63d16e790ac78c5854bb12374f45d6118eWu-cheng Li                    pkg = getAttribute(tree, NULL, "package", NULL);
1146f05c1d63d16e790ac78c5854bb12374f45d6118eWu-cheng Li                    printf("package: name='%s' ",
1147f05c1d63d16e790ac78c5854bb12374f45d6118eWu-cheng Li                            ResTable::normalizeForOutput(pkg.string()).string());
1148f05c1d63d16e790ac78c5854bb12374f45d6118eWu-cheng Li                    int32_t versionCode = getIntegerAttribute(tree, VERSION_CODE_ATTR, &error);
1149f05c1d63d16e790ac78c5854bb12374f45d6118eWu-cheng Li                    if (error != "") {
1150f05c1d63d16e790ac78c5854bb12374f45d6118eWu-cheng Li                        fprintf(stderr, "ERROR getting 'android:versionCode' attribute: %s\n", error.string());
1151f05c1d63d16e790ac78c5854bb12374f45d6118eWu-cheng Li                        goto bail;
1152f05c1d63d16e790ac78c5854bb12374f45d6118eWu-cheng Li                    }
1153244f8c26365a303d9dd861bd48a29a4b48578da1Chih-Chung Chang                    if (versionCode > 0) {
1154244f8c26365a303d9dd861bd48a29a4b48578da1Chih-Chung Chang                        printf("versionCode='%d' ", versionCode);
1155244f8c26365a303d9dd861bd48a29a4b48578da1Chih-Chung Chang                    } else {
1156244f8c26365a303d9dd861bd48a29a4b48578da1Chih-Chung Chang                        printf("versionCode='' ");
11579d062cfe94dcd24b1d61fc83e5de565cb67965b1Wu-cheng Li                    }
11589d062cfe94dcd24b1d61fc83e5de565cb67965b1Wu-cheng Li                    String8 versionName = getResolvedAttribute(&res, tree, VERSION_NAME_ATTR, &error);
11596574539baecc8610529596554b7bca0f21b334b8Wu-cheng Li                    if (error != "") {
11606574539baecc8610529596554b7bca0f21b334b8Wu-cheng Li                        fprintf(stderr, "ERROR getting 'android:versionName' attribute: %s\n", error.string());
11616574539baecc8610529596554b7bca0f21b334b8Wu-cheng Li                        goto bail;
11626574539baecc8610529596554b7bca0f21b334b8Wu-cheng Li                    }
11639d062cfe94dcd24b1d61fc83e5de565cb67965b1Wu-cheng Li                    printf("versionName='%s'",
11649d062cfe94dcd24b1d61fc83e5de565cb67965b1Wu-cheng Li                            ResTable::normalizeForOutput(versionName.string()).string());
11659d062cfe94dcd24b1d61fc83e5de565cb67965b1Wu-cheng Li
11669d062cfe94dcd24b1d61fc83e5de565cb67965b1Wu-cheng Li                    String8 splitName = getAttribute(tree, NULL, "split", NULL);
11679d062cfe94dcd24b1d61fc83e5de565cb67965b1Wu-cheng Li                    if (!splitName.isEmpty()) {
11689d062cfe94dcd24b1d61fc83e5de565cb67965b1Wu-cheng Li                        printf(" split='%s'", ResTable::normalizeForOutput(
11699d062cfe94dcd24b1d61fc83e5de565cb67965b1Wu-cheng Li                                    splitName.string()).string());
11706574539baecc8610529596554b7bca0f21b334b8Wu-cheng Li                    }
11719d062cfe94dcd24b1d61fc83e5de565cb67965b1Wu-cheng Li                    printf("\n");
11729d062cfe94dcd24b1d61fc83e5de565cb67965b1Wu-cheng Li                } else if (depth == 2) {
11739d062cfe94dcd24b1d61fc83e5de565cb67965b1Wu-cheng Li                    withinApplication = false;
11749d062cfe94dcd24b1d61fc83e5de565cb67965b1Wu-cheng Li                    if (tag == "application") {
11759d062cfe94dcd24b1d61fc83e5de565cb67965b1Wu-cheng Li                        withinApplication = true;
11769d062cfe94dcd24b1d61fc83e5de565cb67965b1Wu-cheng Li
11779d062cfe94dcd24b1d61fc83e5de565cb67965b1Wu-cheng Li                        String8 label;
11789d062cfe94dcd24b1d61fc83e5de565cb67965b1Wu-cheng Li                        const size_t NL = locales.size();
11799d062cfe94dcd24b1d61fc83e5de565cb67965b1Wu-cheng Li                        for (size_t i=0; i<NL; i++) {
11809d062cfe94dcd24b1d61fc83e5de565cb67965b1Wu-cheng Li                            const char* localeStr =  locales[i].string();
11819d062cfe94dcd24b1d61fc83e5de565cb67965b1Wu-cheng Li                            assets.setLocale(localeStr != NULL ? localeStr : "");
11829d062cfe94dcd24b1d61fc83e5de565cb67965b1Wu-cheng Li                            String8 llabel = getResolvedAttribute(&res, tree, LABEL_ATTR, &error);
11839d062cfe94dcd24b1d61fc83e5de565cb67965b1Wu-cheng Li                            if (llabel != "") {
11849d062cfe94dcd24b1d61fc83e5de565cb67965b1Wu-cheng Li                                if (localeStr == NULL || strlen(localeStr) == 0) {
11859d062cfe94dcd24b1d61fc83e5de565cb67965b1Wu-cheng Li                                    label = llabel;
11869d062cfe94dcd24b1d61fc83e5de565cb67965b1Wu-cheng Li                                    printf("application-label:'%s'\n",
11879d062cfe94dcd24b1d61fc83e5de565cb67965b1Wu-cheng Li                                            ResTable::normalizeForOutput(llabel.string()).string());
1188bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                                } else {
1189bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                                    if (label == "") {
1190bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                                        label = llabel;
11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    }
11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    printf("application-label-%s:'%s'\n", localeStr,
11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                           ResTable::normalizeForOutput(llabel.string()).string());
11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                }
1195bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                            }
1196bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                        }
1197bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor
1198bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                        ResTable_config tmpConfig = config;
1199bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                        const size_t ND = densities.size();
12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        for (size_t i=0; i<ND; i++) {
12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            tmpConfig.density = densities[i];
12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            assets.setConfiguration(tmpConfig);
12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            String8 icon = getResolvedAttribute(&res, tree, ICON_ATTR, &error);
12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (icon != "") {
1205bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                                printf("application-icon-%d:'%s'\n", densities[i],
1206bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                                        ResTable::normalizeForOutput(icon.string()).string());
1207bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                            }
12089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        assets.setConfiguration(config);
12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1211bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                        String8 icon = getResolvedAttribute(&res, tree, ICON_ATTR, &error);
1212bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                        if (error != "") {
1213bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                            fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n", error.string());
12149b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                            goto bail;
12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        int32_t testOnly = getIntegerAttribute(tree, TEST_ONLY_ATTR, &error, 0);
12179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (error != "") {
12189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            fprintf(stderr, "ERROR getting 'android:testOnly' attribute: %s\n", error.string());
12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            goto bail;
12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        printf("application: label='%s' ",
1222bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                                ResTable::normalizeForOutput(label.string()).string());
12239b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                        printf("icon='%s'\n", ResTable::normalizeForOutput(icon.string()).string());
1224bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                        if (testOnly != 0) {
12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            printf("testOnly='%d'\n", testOnly);
12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1228e8b26e197f7c5e4acbdf8a5cd3f014fbc242c8abDave Sparks                        int32_t debuggable = getResolvedIntegerAttribute(&res, tree, DEBUGGABLE_ATTR, &error, 0);
1229e8b26e197f7c5e4acbdf8a5cd3f014fbc242c8abDave Sparks                        if (error != "") {
1230e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong                            fprintf(stderr, "ERROR getting 'android:debuggable' attribute: %s\n", error.string());
1231e8b26e197f7c5e4acbdf8a5cd3f014fbc242c8abDave Sparks                            goto bail;
1232e8b26e197f7c5e4acbdf8a5cd3f014fbc242c8abDave Sparks                        }
12339b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                        if (debuggable != 0) {
12349b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                            printf("application-debuggable\n");
12359b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                        }
12369b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                    } else if (tag == "uses-sdk") {
12379b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                        int32_t code = getIntegerAttribute(tree, MIN_SDK_VERSION_ATTR, &error);
1238e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong                        if (error != "") {
1239e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong                            error = "";
12409b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                            String8 name = getResolvedAttribute(&res, tree, MIN_SDK_VERSION_ATTR, &error);
12419b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                            if (error != "") {
12429b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                                fprintf(stderr, "ERROR getting 'android:minSdkVersion' attribute: %s\n",
12439b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                                        error.string());
12449b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                                goto bail;
1245e8b26e197f7c5e4acbdf8a5cd3f014fbc242c8abDave Sparks                            }
1246bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                            if (name == "Donut") targetSdk = 4;
1247bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                            printf("sdkVersion:'%s'\n",
1248bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                                    ResTable::normalizeForOutput(name.string()).string());
124942419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li                        } else if (code != -1) {
125042419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li                            targetSdk = code;
125142419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li                            printf("sdkVersion:'%d'\n", code);
125240057ce749c8c4d274db0352a2af4344bda92dbaWu-cheng Li                        }
1253bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                        code = getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR, NULL, -1);
1254bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                        if (code != -1) {
125540057ce749c8c4d274db0352a2af4344bda92dbaWu-cheng Li                            printf("maxSdkVersion:'%d'\n", code);
1256bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                        }
1257bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                        code = getIntegerAttribute(tree, TARGET_SDK_VERSION_ATTR, &error);
1258e8b26e197f7c5e4acbdf8a5cd3f014fbc242c8abDave Sparks                        if (error != "") {
1259bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                            error = "";
1260e8b26e197f7c5e4acbdf8a5cd3f014fbc242c8abDave Sparks                            String8 name = getResolvedAttribute(&res, tree, TARGET_SDK_VERSION_ATTR, &error);
1261e8b26e197f7c5e4acbdf8a5cd3f014fbc242c8abDave Sparks                            if (error != "") {
1262e8b26e197f7c5e4acbdf8a5cd3f014fbc242c8abDave Sparks                                fprintf(stderr, "ERROR getting 'android:targetSdkVersion' attribute: %s\n",
12639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                        error.string());
12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                goto bail;
1265e8b26e197f7c5e4acbdf8a5cd3f014fbc242c8abDave Sparks                            }
12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (name == "Donut" && targetSdk < 4) targetSdk = 4;
1267e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong                            printf("targetSdkVersion:'%s'\n",
1268e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong                                    ResTable::normalizeForOutput(name.string()).string());
1269e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong                        } else if (code != -1) {
1270e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong                            if (targetSdk < code) {
1271e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong                                targetSdk = code;
1272e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong                            }
1273e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong                            printf("targetSdkVersion:'%d'\n", code);
1274e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong                        }
1275e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong                    } else if (tag == "uses-configuration") {
1276e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong                        int32_t reqTouchScreen = getIntegerAttribute(tree,
1277e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong                                REQ_TOUCH_SCREEN_ATTR, NULL, 0);
1278e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong                        int32_t reqKeyboardType = getIntegerAttribute(tree,
1279e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong                                REQ_KEYBOARD_TYPE_ATTR, NULL, 0);
1280e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong                        int32_t reqHardKeyboard = getIntegerAttribute(tree,
1281e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong                                REQ_HARD_KEYBOARD_ATTR, NULL, 0);
1282e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong                        int32_t reqNavigation = getIntegerAttribute(tree,
1283e00cab707dcaf6f05adb5ccb9c80fdf25c483427James Dong                                REQ_NAVIGATION_ATTR, NULL, 0);
1284e9c6c9ccfde7a642a4c0554e2d066f3dbbea98ceWu-cheng Li                        int32_t reqFiveWayNav = getIntegerAttribute(tree,
12859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                REQ_FIVE_WAY_NAV_ATTR, NULL, 0);
12869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        printf("uses-configuration:");
1287e8b26e197f7c5e4acbdf8a5cd3f014fbc242c8abDave Sparks                        if (reqTouchScreen != 0) {
1288bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                            printf(" reqTouchScreen='%d'", reqTouchScreen);
12893f4639a6611222ae1ae5493de49213250d292139Wu-cheng Li                        }
12903f4639a6611222ae1ae5493de49213250d292139Wu-cheng Li                        if (reqKeyboardType != 0) {
1291bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                            printf(" reqKeyboardType='%d'", reqKeyboardType);
1292bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                        }
1293bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                        if (reqHardKeyboard != 0) {
1294bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                            printf(" reqHardKeyboard='%d'", reqHardKeyboard);
1295bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                        }
1296bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                        if (reqNavigation != 0) {
1297bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                            printf(" reqNavigation='%d'", reqNavigation);
1298bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                        }
1299bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                        if (reqFiveWayNav != 0) {
130036f68b8f24df906c969581b0b8e1a47f95dc03cbWu-cheng Li                            printf(" reqFiveWayNav='%d'", reqFiveWayNav);
130136f68b8f24df906c969581b0b8e1a47f95dc03cbWu-cheng Li                        }
130236f68b8f24df906c969581b0b8e1a47f95dc03cbWu-cheng Li                        printf("\n");
13030ca25191c663ef229f1f475b17899f2017ed6980Wu-cheng Li                    } else if (tag == "supports-input") {
13040ca25191c663ef229f1f475b17899f2017ed6980Wu-cheng Li                        withinSupportsInput = true;
1305bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                    } else if (tag == "supports-screens") {
130636f68b8f24df906c969581b0b8e1a47f95dc03cbWu-cheng Li                        smallScreen = getIntegerAttribute(tree,
130736f68b8f24df906c969581b0b8e1a47f95dc03cbWu-cheng Li                                SMALL_SCREEN_ATTR, NULL, 1);
130836f68b8f24df906c969581b0b8e1a47f95dc03cbWu-cheng Li                        normalScreen = getIntegerAttribute(tree,
130936f68b8f24df906c969581b0b8e1a47f95dc03cbWu-cheng Li                                NORMAL_SCREEN_ATTR, NULL, 1);
1310bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                        largeScreen = getIntegerAttribute(tree,
13113f4639a6611222ae1ae5493de49213250d292139Wu-cheng Li                                LARGE_SCREEN_ATTR, NULL, 1);
13123f4639a6611222ae1ae5493de49213250d292139Wu-cheng Li                        xlargeScreen = getIntegerAttribute(tree,
13138cbb8f5e1f939b03515cb4d5942c3fcb226efb9eWu-cheng Li                                XLARGE_SCREEN_ATTR, NULL, 1);
13140ca25191c663ef229f1f475b17899f2017ed6980Wu-cheng Li                        anyDensity = getIntegerAttribute(tree,
13150ca25191c663ef229f1f475b17899f2017ed6980Wu-cheng Li                                ANY_DENSITY_ATTR, NULL, 1);
131636f68b8f24df906c969581b0b8e1a47f95dc03cbWu-cheng Li                        requiresSmallestWidthDp = getIntegerAttribute(tree,
131736f68b8f24df906c969581b0b8e1a47f95dc03cbWu-cheng Li                                REQUIRES_SMALLEST_WIDTH_DP_ATTR, NULL, 0);
131836f68b8f24df906c969581b0b8e1a47f95dc03cbWu-cheng Li                        compatibleWidthLimitDp = getIntegerAttribute(tree,
131936f68b8f24df906c969581b0b8e1a47f95dc03cbWu-cheng Li                                COMPATIBLE_WIDTH_LIMIT_DP_ATTR, NULL, 0);
13202fe6fcaff4bdab45484055d6c18dd96d1b7b7be1Wu-cheng Li                        largestWidthLimitDp = getIntegerAttribute(tree,
13212fe6fcaff4bdab45484055d6c18dd96d1b7b7be1Wu-cheng Li                                LARGEST_WIDTH_LIMIT_DP_ATTR, NULL, 0);
13222fe6fcaff4bdab45484055d6c18dd96d1b7b7be1Wu-cheng Li                    } else if (tag == "feature-group") {
1323b982fb4fd36a3cd24a0bb17c964139fe4c9cbb47Wu-cheng Li                        withinFeatureGroup = true;
1324b982fb4fd36a3cd24a0bb17c964139fe4c9cbb47Wu-cheng Li                        FeatureGroup group;
1325b982fb4fd36a3cd24a0bb17c964139fe4c9cbb47Wu-cheng Li                        group.label = getResolvedAttribute(&res, tree, LABEL_ATTR, &error);
1326d1d7706fce19a9a0cf71ff9b65f3aba9b89eeb3bChih-Chung Chang                        if (error != "") {
132769ea4e15e52c456537575d21443ac1efdb03a902Brad Fitzpatrick                            fprintf(stderr, "ERROR getting 'android:label' attribute:"
13282fe6fcaff4bdab45484055d6c18dd96d1b7b7be1Wu-cheng Li                                    " %s\n", error.string());
13292fe6fcaff4bdab45484055d6c18dd96d1b7b7be1Wu-cheng Li                            goto bail;
1330d1d7706fce19a9a0cf71ff9b65f3aba9b89eeb3bChih-Chung Chang                        }
133169ea4e15e52c456537575d21443ac1efdb03a902Brad Fitzpatrick                        featureGroups.add(group);
133269ea4e15e52c456537575d21443ac1efdb03a902Brad Fitzpatrick
1333b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang                    } else if (tag == "uses-feature") {
1334724c52244423feced2677fbd1f905e0b8b0639f2Chih-Chung Chang                        String8 name = getAttribute(tree, NAME_ATTR, &error);
1335724c52244423feced2677fbd1f905e0b8b0639f2Chih-Chung Chang                        if (name != "" && error == "") {
1336724c52244423feced2677fbd1f905e0b8b0639f2Chih-Chung Chang                            int req = getIntegerAttribute(tree,
1337724c52244423feced2677fbd1f905e0b8b0639f2Chih-Chung Chang                                    REQUIRED_ATTR, NULL, 1);
1338724c52244423feced2677fbd1f905e0b8b0639f2Chih-Chung Chang
1339724c52244423feced2677fbd1f905e0b8b0639f2Chih-Chung Chang                            commonFeatures.features.add(name, req);
1340724c52244423feced2677fbd1f905e0b8b0639f2Chih-Chung Chang                            if (req) {
1341724c52244423feced2677fbd1f905e0b8b0639f2Chih-Chung Chang                                addParentFeatures(&commonFeatures, name);
1342724c52244423feced2677fbd1f905e0b8b0639f2Chih-Chung Chang                            }
1343724c52244423feced2677fbd1f905e0b8b0639f2Chih-Chung Chang                        } else {
1344724c52244423feced2677fbd1f905e0b8b0639f2Chih-Chung Chang                            int vers = getIntegerAttribute(tree,
1345724c52244423feced2677fbd1f905e0b8b0639f2Chih-Chung Chang                                    GL_ES_VERSION_ATTR, &error);
1346724c52244423feced2677fbd1f905e0b8b0639f2Chih-Chung Chang                            if (error == "") {
1347724c52244423feced2677fbd1f905e0b8b0639f2Chih-Chung Chang                                if (vers > commonFeatures.openGLESVersion) {
1348b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang                                    commonFeatures.openGLESVersion = vers;
13492fe6fcaff4bdab45484055d6c18dd96d1b7b7be1Wu-cheng Li                                }
13502fe6fcaff4bdab45484055d6c18dd96d1b7b7be1Wu-cheng Li                            }
13512fe6fcaff4bdab45484055d6c18dd96d1b7b7be1Wu-cheng Li                        }
13522fe6fcaff4bdab45484055d6c18dd96d1b7b7be1Wu-cheng Li                    } else if (tag == "uses-permission") {
13532fe6fcaff4bdab45484055d6c18dd96d1b7b7be1Wu-cheng Li                        String8 name = getAttribute(tree, NAME_ATTR, &error);
13542fe6fcaff4bdab45484055d6c18dd96d1b7b7be1Wu-cheng Li                        if (name != "" && error == "") {
13552fe6fcaff4bdab45484055d6c18dd96d1b7b7be1Wu-cheng Li                            if (name == "android.permission.CAMERA") {
1356724c52244423feced2677fbd1f905e0b8b0639f2Chih-Chung Chang                                addImpliedFeature(&impliedFeatures, "android.hardware.camera",
1357724c52244423feced2677fbd1f905e0b8b0639f2Chih-Chung Chang                                        String8::format("requested %s permission", name.string())
1358b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang                                        .string());
1359d303362ac21fb9de40f2f2366cbe7ecaa113dc12Wu-cheng Li                            } else if (name == "android.permission.ACCESS_FINE_LOCATION") {
1360d303362ac21fb9de40f2f2366cbe7ecaa113dc12Wu-cheng Li                                addImpliedFeature(&impliedFeatures, "android.hardware.location.gps",
1361d303362ac21fb9de40f2f2366cbe7ecaa113dc12Wu-cheng Li                                        String8::format("requested %s permission", name.string())
1362d303362ac21fb9de40f2f2366cbe7ecaa113dc12Wu-cheng Li                                        .string());
1363d1d7706fce19a9a0cf71ff9b65f3aba9b89eeb3bChih-Chung Chang                                addImpliedFeature(&impliedFeatures, "android.hardware.location",
1364e7bd22a9d9441916aa9c67d80ee9f02a2d3e10e5Chih-Chung Chang                                        String8::format("requested %s permission", name.string())
1365e7bd22a9d9441916aa9c67d80ee9f02a2d3e10e5Chih-Chung Chang                                        .string());
13662fe6fcaff4bdab45484055d6c18dd96d1b7b7be1Wu-cheng Li                            } else if (name == "android.permission.ACCESS_MOCK_LOCATION") {
1367d1d7706fce19a9a0cf71ff9b65f3aba9b89eeb3bChih-Chung Chang                                addImpliedFeature(&impliedFeatures, "android.hardware.location",
1368d1d7706fce19a9a0cf71ff9b65f3aba9b89eeb3bChih-Chung Chang                                        String8::format("requested %s permission", name.string())
1369d1d7706fce19a9a0cf71ff9b65f3aba9b89eeb3bChih-Chung Chang                                        .string());
1370d1d7706fce19a9a0cf71ff9b65f3aba9b89eeb3bChih-Chung Chang                            } else if (name == "android.permission.ACCESS_COARSE_LOCATION") {
1371487acdfb4eca3859fd688a1ff0a32fe6314b68f6Eino-Ville Talvala                                addImpliedFeature(&impliedFeatures, "android.hardware.location.network",
137269fe527bea12f262bfb1a5838f40e3433ad3cb78Eino-Ville Talvala                                        String8::format("requested %s permission", name.string())
1373487acdfb4eca3859fd688a1ff0a32fe6314b68f6Eino-Ville Talvala                                        .string());
1374487acdfb4eca3859fd688a1ff0a32fe6314b68f6Eino-Ville Talvala                                addImpliedFeature(&impliedFeatures, "android.hardware.location",
1375487acdfb4eca3859fd688a1ff0a32fe6314b68f6Eino-Ville Talvala                                        String8::format("requested %s permission", name.string())
1376487acdfb4eca3859fd688a1ff0a32fe6314b68f6Eino-Ville Talvala                                        .string());
1377487acdfb4eca3859fd688a1ff0a32fe6314b68f6Eino-Ville Talvala                            } else if (name == "android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" ||
137869fe527bea12f262bfb1a5838f40e3433ad3cb78Eino-Ville Talvala                                       name == "android.permission.INSTALL_LOCATION_PROVIDER") {
1379487acdfb4eca3859fd688a1ff0a32fe6314b68f6Eino-Ville Talvala                                addImpliedFeature(&impliedFeatures, "android.hardware.location",
1380487acdfb4eca3859fd688a1ff0a32fe6314b68f6Eino-Ville Talvala                                        String8::format("requested %s permission", name.string())
1381487acdfb4eca3859fd688a1ff0a32fe6314b68f6Eino-Ville Talvala                                        .string());
1382487acdfb4eca3859fd688a1ff0a32fe6314b68f6Eino-Ville Talvala                            } else if (name == "android.permission.BLUETOOTH" ||
1383487acdfb4eca3859fd688a1ff0a32fe6314b68f6Eino-Ville Talvala                                       name == "android.permission.BLUETOOTH_ADMIN") {
138469fe527bea12f262bfb1a5838f40e3433ad3cb78Eino-Ville Talvala                                if (targetSdk > 4) {
138569fe527bea12f262bfb1a5838f40e3433ad3cb78Eino-Ville Talvala                                    addImpliedFeature(&impliedFeatures, "android.hardware.bluetooth",
138669fe527bea12f262bfb1a5838f40e3433ad3cb78Eino-Ville Talvala                                            String8::format("requested %s permission", name.string())
1387487acdfb4eca3859fd688a1ff0a32fe6314b68f6Eino-Ville Talvala                                            .string());
1388487acdfb4eca3859fd688a1ff0a32fe6314b68f6Eino-Ville Talvala                                    addImpliedFeature(&impliedFeatures, "android.hardware.bluetooth",
1389487acdfb4eca3859fd688a1ff0a32fe6314b68f6Eino-Ville Talvala                                            "targetSdkVersion > 4");
1390487acdfb4eca3859fd688a1ff0a32fe6314b68f6Eino-Ville Talvala                                }
139169fe527bea12f262bfb1a5838f40e3433ad3cb78Eino-Ville Talvala                            } else if (name == "android.permission.RECORD_AUDIO") {
1392487acdfb4eca3859fd688a1ff0a32fe6314b68f6Eino-Ville Talvala                                addImpliedFeature(&impliedFeatures, "android.hardware.microphone",
139369fe527bea12f262bfb1a5838f40e3433ad3cb78Eino-Ville Talvala                                        String8::format("requested %s permission", name.string())
139469fe527bea12f262bfb1a5838f40e3433ad3cb78Eino-Ville Talvala                                        .string());
13954f8e5ce21df881796d05a1b2117dd8868570a57bEino-Ville Talvala                            } else if (name == "android.permission.ACCESS_WIFI_STATE" ||
13964f8e5ce21df881796d05a1b2117dd8868570a57bEino-Ville Talvala                                       name == "android.permission.CHANGE_WIFI_STATE" ||
13974f8e5ce21df881796d05a1b2117dd8868570a57bEino-Ville Talvala                                       name == "android.permission.CHANGE_WIFI_MULTICAST_STATE") {
13984f8e5ce21df881796d05a1b2117dd8868570a57bEino-Ville Talvala                                addImpliedFeature(&impliedFeatures, "android.hardware.wifi",
13994f8e5ce21df881796d05a1b2117dd8868570a57bEino-Ville Talvala                                        String8::format("requested %s permission", name.string())
14004f8e5ce21df881796d05a1b2117dd8868570a57bEino-Ville Talvala                                        .string());
14014f8e5ce21df881796d05a1b2117dd8868570a57bEino-Ville Talvala                            } else if (name == "android.permission.CALL_PHONE" ||
14024f8e5ce21df881796d05a1b2117dd8868570a57bEino-Ville Talvala                                       name == "android.permission.CALL_PRIVILEGED" ||
14034f8e5ce21df881796d05a1b2117dd8868570a57bEino-Ville Talvala                                       name == "android.permission.MODIFY_PHONE_STATE" ||
14044f8e5ce21df881796d05a1b2117dd8868570a57bEino-Ville Talvala                                       name == "android.permission.PROCESS_OUTGOING_CALLS" ||
14054f8e5ce21df881796d05a1b2117dd8868570a57bEino-Ville Talvala                                       name == "android.permission.READ_SMS" ||
14064f8e5ce21df881796d05a1b2117dd8868570a57bEino-Ville Talvala                                       name == "android.permission.RECEIVE_SMS" ||
14074f8e5ce21df881796d05a1b2117dd8868570a57bEino-Ville Talvala                                       name == "android.permission.RECEIVE_MMS" ||
14084f8e5ce21df881796d05a1b2117dd8868570a57bEino-Ville Talvala                                       name == "android.permission.RECEIVE_WAP_PUSH" ||
140969fe527bea12f262bfb1a5838f40e3433ad3cb78Eino-Ville Talvala                                       name == "android.permission.SEND_SMS" ||
141069fe527bea12f262bfb1a5838f40e3433ad3cb78Eino-Ville Talvala                                       name == "android.permission.WRITE_APN_SETTINGS" ||
1411bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                                       name == "android.permission.WRITE_SMS") {
1412bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                                addImpliedFeature(&impliedFeatures, "android.hardware.telephony",
1413bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                                        String8("requested a telephony permission").string());
1414bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                            } else if (name == "android.permission.WRITE_EXTERNAL_STORAGE") {
1415e8b26e197f7c5e4acbdf8a5cd3f014fbc242c8abDave Sparks                                hasWriteExternalStoragePermission = true;
14163f4639a6611222ae1ae5493de49213250d292139Wu-cheng Li                            } else if (name == "android.permission.READ_EXTERNAL_STORAGE") {
1417e8b26e197f7c5e4acbdf8a5cd3f014fbc242c8abDave Sparks                                hasReadExternalStoragePermission = true;
1418e8b26e197f7c5e4acbdf8a5cd3f014fbc242c8abDave Sparks                            } else if (name == "android.permission.READ_PHONE_STATE") {
1419bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                                hasReadPhoneStatePermission = true;
142036f68b8f24df906c969581b0b8e1a47f95dc03cbWu-cheng Li                            } else if (name == "android.permission.READ_CONTACTS") {
142136f68b8f24df906c969581b0b8e1a47f95dc03cbWu-cheng Li                                hasReadContactsPermission = true;
14223f4639a6611222ae1ae5493de49213250d292139Wu-cheng Li                            } else if (name == "android.permission.WRITE_CONTACTS") {
142336f68b8f24df906c969581b0b8e1a47f95dc03cbWu-cheng Li                                hasWriteContactsPermission = true;
142436f68b8f24df906c969581b0b8e1a47f95dc03cbWu-cheng Li                            } else if (name == "android.permission.READ_CALL_LOG") {
1425e8b26e197f7c5e4acbdf8a5cd3f014fbc242c8abDave Sparks                                hasReadCallLogPermission = true;
1426e8b26e197f7c5e4acbdf8a5cd3f014fbc242c8abDave Sparks                            } else if (name == "android.permission.WRITE_CALL_LOG") {
14273f4639a6611222ae1ae5493de49213250d292139Wu-cheng Li                                hasWriteCallLogPermission = true;
1428e8b26e197f7c5e4acbdf8a5cd3f014fbc242c8abDave Sparks                            }
1429e8b26e197f7c5e4acbdf8a5cd3f014fbc242c8abDave Sparks
1430e8b26e197f7c5e4acbdf8a5cd3f014fbc242c8abDave Sparks                            printUsesPermission(name,
14313f4639a6611222ae1ae5493de49213250d292139Wu-cheng Li                                    getIntegerAttribute(tree, REQUIRED_ATTR, NULL, 1) == 0,
143236f68b8f24df906c969581b0b8e1a47f95dc03cbWu-cheng Li                                    getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR, NULL, -1));
14338cbb8f5e1f939b03515cb4d5942c3fcb226efb9eWu-cheng Li                       } else {
14343f4639a6611222ae1ae5493de49213250d292139Wu-cheng Li                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
14358cbb8f5e1f939b03515cb4d5942c3fcb226efb9eWu-cheng Li                                    error.string());
1436e8b26e197f7c5e4acbdf8a5cd3f014fbc242c8abDave Sparks                            goto bail;
14373f4639a6611222ae1ae5493de49213250d292139Wu-cheng Li                        }
1438e8b26e197f7c5e4acbdf8a5cd3f014fbc242c8abDave Sparks                    } else if (tag == "uses-package") {
14393f4639a6611222ae1ae5493de49213250d292139Wu-cheng Li                        String8 name = getAttribute(tree, NAME_ATTR, &error);
1440e8b26e197f7c5e4acbdf8a5cd3f014fbc242c8abDave Sparks                        if (name != "" && error == "") {
14419b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                            printf("uses-package:'%s'\n",
14424c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                                    ResTable::normalizeForOutput(name.string()).string());
14434c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                        } else {
14444c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
14454c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                                    error.string());
14464c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                                goto bail;
14474c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                        }
14484c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                    } else if (tag == "original-package") {
14494c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                        String8 name = getAttribute(tree, NAME_ATTR, &error);
14504c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                        if (name != "" && error == "") {
145153b30912d3e8598c05e47308981971e958e98db2Wu-cheng Li                            printf("original-package:'%s'\n",
1452464cb21e2aaa448072449b82156f18bd64c0e613Joe Fernandez                                    ResTable::normalizeForOutput(name.string()).string());
14534c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                        } else {
1454f0d6a48c6ad852b84687127f14b1ffde02416dc4Wu-cheng Li                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
14554c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                                    error.string());
14564c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                                goto bail;
14574c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                        }
1458c0c683b3344c67700882f8059e7d18266366daa9Wu-cheng Li                    } else if (tag == "supports-gl-texture") {
14594c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                        String8 name = getAttribute(tree, NAME_ATTR, &error);
14604c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                        if (name != "" && error == "") {
14614c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                            printf("supports-gl-texture:'%s'\n",
1462c0c683b3344c67700882f8059e7d18266366daa9Wu-cheng Li                                    ResTable::normalizeForOutput(name.string()).string());
14634c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                        } else {
14644c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
14654c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                                    error.string());
14664c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                                goto bail;
14674c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                        }
14684c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                    } else if (tag == "compatible-screens") {
14694c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                        printCompatibleScreens(tree, &error);
1470c0c683b3344c67700882f8059e7d18266366daa9Wu-cheng Li                        if (error != "") {
14714c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                            fprintf(stderr, "ERROR getting compatible screens: %s\n",
14724c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                                    error.string());
14734c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                            goto bail;
14744c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                        }
1475c0c683b3344c67700882f8059e7d18266366daa9Wu-cheng Li                        depth--;
14764c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                    } else if (tag == "package-verifier") {
14774c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                        String8 name = getAttribute(tree, NAME_ATTR, &error);
14788c13670c13a7a965884d92193b039e26c96b95c6Wu-cheng Li                        if (name != "" && error == "") {
14794c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                            String8 publicKey = getAttribute(tree, PUBLIC_KEY_ATTR, &error);
14808c13670c13a7a965884d92193b039e26c96b95c6Wu-cheng Li                            if (publicKey != "" && error == "") {
14818c13670c13a7a965884d92193b039e26c96b95c6Wu-cheng Li                                printf("package-verifier: name='%s' publicKey='%s'\n",
14828c13670c13a7a965884d92193b039e26c96b95c6Wu-cheng Li                                        ResTable::normalizeForOutput(name.string()).string(),
14838c13670c13a7a965884d92193b039e26c96b95c6Wu-cheng Li                                        ResTable::normalizeForOutput(publicKey.string()).string());
14848c13670c13a7a965884d92193b039e26c96b95c6Wu-cheng Li                            }
14858c13670c13a7a965884d92193b039e26c96b95c6Wu-cheng Li                        }
14868c13670c13a7a965884d92193b039e26c96b95c6Wu-cheng Li                    }
14878c13670c13a7a965884d92193b039e26c96b95c6Wu-cheng Li                } else if (depth == 3) {
14888c13670c13a7a965884d92193b039e26c96b95c6Wu-cheng Li                    withinActivity = false;
14898c13670c13a7a965884d92193b039e26c96b95c6Wu-cheng Li                    withinReceiver = false;
14908c13670c13a7a965884d92193b039e26c96b95c6Wu-cheng Li                    withinService = false;
14918c13670c13a7a965884d92193b039e26c96b95c6Wu-cheng Li                    withinProvider = false;
14928c13670c13a7a965884d92193b039e26c96b95c6Wu-cheng Li                    hasIntentFilter = false;
14934c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                    hasMetaHostPaymentCategory = false;
1494c0c683b3344c67700882f8059e7d18266366daa9Wu-cheng Li                    hasMetaOffHostPaymentCategory = false;
14954c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                    hasBindDeviceAdminPermission = false;
14964c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                    hasBindInputMethodPermission = false;
14974c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                    hasBindAccessibilityServicePermission = false;
14984c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                    hasBindPrintServicePermission = false;
1499c0c683b3344c67700882f8059e7d18266366daa9Wu-cheng Li                    hasBindNfcServicePermission = false;
15004c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                    hasRequiredSafAttributes = false;
1501c0c683b3344c67700882f8059e7d18266366daa9Wu-cheng Li                    hasBindNotificationListenerServicePermission = false;
15024c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                    hasBindDreamServicePermission = false;
15034c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                    if (withinApplication) {
15044c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                        if(tag == "activity") {
1505c0c683b3344c67700882f8059e7d18266366daa9Wu-cheng Li                            withinActivity = true;
15064c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                            activityName = getAttribute(tree, NAME_ATTR, &error);
15074c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                            if (error != "") {
15084c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                                fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
15094c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                                        error.string());
1510c0c683b3344c67700882f8059e7d18266366daa9Wu-cheng Li                                goto bail;
15114c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                            }
1512464cb21e2aaa448072449b82156f18bd64c0e613Joe Fernandez
15134c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                            activityLabel = getResolvedAttribute(&res, tree, LABEL_ATTR, &error);
15144c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                            if (error != "") {
15154c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                                fprintf(stderr, "ERROR getting 'android:label' attribute: %s\n",
15164c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                                        error.string());
15174c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                                goto bail;
15184c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                            }
15194c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li
15204c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                            activityIcon = getResolvedAttribute(&res, tree, ICON_ATTR, &error);
15214c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                            if (error != "") {
15224c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                                fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n",
1523464cb21e2aaa448072449b82156f18bd64c0e613Joe Fernandez                                        error.string());
152453b30912d3e8598c05e47308981971e958e98db2Wu-cheng Li                                goto bail;
1525464cb21e2aaa448072449b82156f18bd64c0e613Joe Fernandez                            }
1526464cb21e2aaa448072449b82156f18bd64c0e613Joe Fernandez
15274c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                            activityBanner = getResolvedAttribute(&res, tree, BANNER_ATTR, &error);
1528464cb21e2aaa448072449b82156f18bd64c0e613Joe Fernandez                            if (error != "") {
15294c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                                fprintf(stderr, "ERROR getting 'android:banner' attribute: %s\n",
1530f0d6a48c6ad852b84687127f14b1ffde02416dc4Wu-cheng Li                                        error.string());
1531c0c683b3344c67700882f8059e7d18266366daa9Wu-cheng Li                                goto bail;
1532c0c683b3344c67700882f8059e7d18266366daa9Wu-cheng Li                            }
1533c0c683b3344c67700882f8059e7d18266366daa9Wu-cheng Li
1534bb1e275c0e684dd213f124da77110cdd9d6f090cWu-cheng Li                            int32_t orien = getResolvedIntegerAttribute(&res, tree,
1535bb1e275c0e684dd213f124da77110cdd9d6f090cWu-cheng Li                                    SCREEN_ORIENTATION_ATTR, &error);
1536bb1e275c0e684dd213f124da77110cdd9d6f090cWu-cheng Li                            if (error == "") {
15374c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                                if (orien == 0 || orien == 6 || orien == 8) {
15384c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                                    // Requests landscape, sensorLandscape, or reverseLandscape.
15394c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                                    addImpliedFeature(&impliedFeatures, "android.hardware.screen.landscape",
1540c0c683b3344c67700882f8059e7d18266366daa9Wu-cheng Li                                            "one or more activities have specified a landscape orientation");
1541c0c683b3344c67700882f8059e7d18266366daa9Wu-cheng Li                                } else if (orien == 1 || orien == 7 || orien == 9) {
15428c13670c13a7a965884d92193b039e26c96b95c6Wu-cheng Li                                    // Requests portrait, sensorPortrait, or reversePortrait.
15438c13670c13a7a965884d92193b039e26c96b95c6Wu-cheng Li                                    addImpliedFeature(&impliedFeatures, "android.hardware.screen.portrait",
15448c13670c13a7a965884d92193b039e26c96b95c6Wu-cheng Li                                            "one or more activities have specified a portrait orientation");
15458c13670c13a7a965884d92193b039e26c96b95c6Wu-cheng Li                                }
1546f0d6a48c6ad852b84687127f14b1ffde02416dc4Wu-cheng Li                            }
1547f0d6a48c6ad852b84687127f14b1ffde02416dc4Wu-cheng Li                        } else if (tag == "uses-library") {
1548f0d6a48c6ad852b84687127f14b1ffde02416dc4Wu-cheng Li                            String8 libraryName = getAttribute(tree, NAME_ATTR, &error);
15498c13670c13a7a965884d92193b039e26c96b95c6Wu-cheng Li                            if (error != "") {
15508c13670c13a7a965884d92193b039e26c96b95c6Wu-cheng Li                                fprintf(stderr,
15518c13670c13a7a965884d92193b039e26c96b95c6Wu-cheng Li                                        "ERROR getting 'android:name' attribute for uses-library"
15528c13670c13a7a965884d92193b039e26c96b95c6Wu-cheng Li                                        " %s\n", error.string());
15538c13670c13a7a965884d92193b039e26c96b95c6Wu-cheng Li                                goto bail;
15548c13670c13a7a965884d92193b039e26c96b95c6Wu-cheng Li                            }
15558c13670c13a7a965884d92193b039e26c96b95c6Wu-cheng Li                            int req = getIntegerAttribute(tree,
15568c13670c13a7a965884d92193b039e26c96b95c6Wu-cheng Li                                    REQUIRED_ATTR, NULL, 1);
15578c13670c13a7a965884d92193b039e26c96b95c6Wu-cheng Li                            printf("uses-library%s:'%s'\n",
15588c13670c13a7a965884d92193b039e26c96b95c6Wu-cheng Li                                    req ? "" : "-not-required", ResTable::normalizeForOutput(
15598c13670c13a7a965884d92193b039e26c96b95c6Wu-cheng Li                                            libraryName.string()).string());
15608c13670c13a7a965884d92193b039e26c96b95c6Wu-cheng Li                        } else if (tag == "receiver") {
15618c13670c13a7a965884d92193b039e26c96b95c6Wu-cheng Li                            withinReceiver = true;
15628c13670c13a7a965884d92193b039e26c96b95c6Wu-cheng Li                            receiverName = getAttribute(tree, NAME_ATTR, &error);
15638c13670c13a7a965884d92193b039e26c96b95c6Wu-cheng Li
15648c13670c13a7a965884d92193b039e26c96b95c6Wu-cheng Li                            if (error != "") {
15658c13670c13a7a965884d92193b039e26c96b95c6Wu-cheng Li                                fprintf(stderr,
15668c13670c13a7a965884d92193b039e26c96b95c6Wu-cheng Li                                        "ERROR getting 'android:name' attribute for receiver:"
15674c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                                        " %s\n", error.string());
1568464cb21e2aaa448072449b82156f18bd64c0e613Joe Fernandez                                goto bail;
15694c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                            }
1570bb1e275c0e684dd213f124da77110cdd9d6f090cWu-cheng Li
15714c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                            String8 permission = getAttribute(tree, PERMISSION_ATTR, &error);
15724c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                            if (error == "") {
15738df3b2b3989df44953153603681e03140fd853d6Eino-Ville Talvala                                if (permission == "android.permission.BIND_DEVICE_ADMIN") {
15748df3b2b3989df44953153603681e03140fd853d6Eino-Ville Talvala                                    hasBindDeviceAdminPermission = true;
15758df3b2b3989df44953153603681e03140fd853d6Eino-Ville Talvala                                }
15768df3b2b3989df44953153603681e03140fd853d6Eino-Ville Talvala                            } else {
15778df3b2b3989df44953153603681e03140fd853d6Eino-Ville Talvala                                fprintf(stderr, "ERROR getting 'android:permission' attribute for"
15788df3b2b3989df44953153603681e03140fd853d6Eino-Ville Talvala                                        " receiver '%s': %s\n", receiverName.string(), error.string());
15798df3b2b3989df44953153603681e03140fd853d6Eino-Ville Talvala                            }
15808df3b2b3989df44953153603681e03140fd853d6Eino-Ville Talvala                        } else if (tag == "service") {
15814c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                            withinService = true;
1582464cb21e2aaa448072449b82156f18bd64c0e613Joe Fernandez                            serviceName = getAttribute(tree, NAME_ATTR, &error);
15834c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li
1584bb1e275c0e684dd213f124da77110cdd9d6f090cWu-cheng Li                            if (error != "") {
1585d52b308916d5f207791788e00bc48baecb90d8b8Wei Hua                                fprintf(stderr, "ERROR getting 'android:name' attribute for "
1586d52b308916d5f207791788e00bc48baecb90d8b8Wei Hua                                        "service:%s\n", error.string());
1587d52b308916d5f207791788e00bc48baecb90d8b8Wei Hua                                goto bail;
1588d52b308916d5f207791788e00bc48baecb90d8b8Wei Hua                            }
1589d52b308916d5f207791788e00bc48baecb90d8b8Wei Hua
1590d52b308916d5f207791788e00bc48baecb90d8b8Wei Hua                            String8 permission = getAttribute(tree, PERMISSION_ATTR, &error);
1591d52b308916d5f207791788e00bc48baecb90d8b8Wei Hua                            if (error == "") {
1592d52b308916d5f207791788e00bc48baecb90d8b8Wei Hua                                if (permission == "android.permission.BIND_INPUT_METHOD") {
1593d52b308916d5f207791788e00bc48baecb90d8b8Wei Hua                                    hasBindInputMethodPermission = true;
1594d52b308916d5f207791788e00bc48baecb90d8b8Wei Hua                                } else if (permission == "android.permission.BIND_ACCESSIBILITY_SERVICE") {
1595d52b308916d5f207791788e00bc48baecb90d8b8Wei Hua                                    hasBindAccessibilityServicePermission = true;
1596d52b308916d5f207791788e00bc48baecb90d8b8Wei Hua                                } else if (permission == "android.permission.BIND_PRINT_SERVICE") {
1597d52b308916d5f207791788e00bc48baecb90d8b8Wei Hua                                    hasBindPrintServicePermission = true;
1598d52b308916d5f207791788e00bc48baecb90d8b8Wei Hua                                } else if (permission == "android.permission.BIND_NFC_SERVICE") {
1599d52b308916d5f207791788e00bc48baecb90d8b8Wei Hua                                    hasBindNfcServicePermission = true;
1600d52b308916d5f207791788e00bc48baecb90d8b8Wei Hua                                } else if (permission == "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE") {
1601d52b308916d5f207791788e00bc48baecb90d8b8Wei Hua                                    hasBindNotificationListenerServicePermission = true;
1602d52b308916d5f207791788e00bc48baecb90d8b8Wei Hua                                } else if (permission == "android.permission.BIND_DREAM_SERVICE") {
1603d52b308916d5f207791788e00bc48baecb90d8b8Wei Hua                                    hasBindDreamServicePermission = true;
1604d52b308916d5f207791788e00bc48baecb90d8b8Wei Hua                                }
1605d52b308916d5f207791788e00bc48baecb90d8b8Wei Hua                            } else {
1606d52b308916d5f207791788e00bc48baecb90d8b8Wei Hua                                fprintf(stderr, "ERROR getting 'android:permission' attribute for"
1607d52b308916d5f207791788e00bc48baecb90d8b8Wei Hua                                        " service '%s': %s\n", serviceName.string(), error.string());
1608d52b308916d5f207791788e00bc48baecb90d8b8Wei Hua                            }
1609d52b308916d5f207791788e00bc48baecb90d8b8Wei Hua                        } else if (tag == "provider") {
1610d52b308916d5f207791788e00bc48baecb90d8b8Wei Hua                            withinProvider = true;
1611d52b308916d5f207791788e00bc48baecb90d8b8Wei Hua
1612d52b308916d5f207791788e00bc48baecb90d8b8Wei Hua                            bool exported = getResolvedIntegerAttribute(&res, tree, EXPORTED_ATTR, &error);
1613d52b308916d5f207791788e00bc48baecb90d8b8Wei Hua                            if (error != "") {
1614d52b308916d5f207791788e00bc48baecb90d8b8Wei Hua                                fprintf(stderr, "ERROR getting 'android:exported' attribute for provider:"
1615d52b308916d5f207791788e00bc48baecb90d8b8Wei Hua                                        " %s\n", error.string());
1616d52b308916d5f207791788e00bc48baecb90d8b8Wei Hua                                goto bail;
1617d52b308916d5f207791788e00bc48baecb90d8b8Wei Hua                            }
1618d52b308916d5f207791788e00bc48baecb90d8b8Wei Hua
1619d52b308916d5f207791788e00bc48baecb90d8b8Wei Hua                            bool grantUriPermissions = getResolvedIntegerAttribute(&res, tree,
1620d52b308916d5f207791788e00bc48baecb90d8b8Wei Hua                                    GRANT_URI_PERMISSIONS_ATTR, &error);
1621d52b308916d5f207791788e00bc48baecb90d8b8Wei Hua                            if (error != "") {
16224c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                                fprintf(stderr, "ERROR getting 'android:grantUriPermissions' attribute for provider:"
16234c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                                        " %s\n", error.string());
1624bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                                goto bail;
1625bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                            }
1626bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor
1627bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                            String8 permission = getResolvedAttribute(&res, tree, PERMISSION_ATTR, &error);
1628bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                            if (error != "") {
1629bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                                fprintf(stderr, "ERROR getting 'android:permission' attribute for provider:"
16309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                        " %s\n", error.string());
1631bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                                goto bail;
1632bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                            }
1633bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor
1634bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                            hasRequiredSafAttributes |= exported && grantUriPermissions &&
1635bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                                permission == "android.permission.MANAGE_DOCUMENTS";
1636bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor
16379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        } else if (bundle->getIncludeMetaData() && tag == "meta-data") {
16389b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                            String8 metaDataName = getResolvedAttribute(&res, tree, NAME_ATTR, &error);
16399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (error != "") {
1640bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                                fprintf(stderr, "ERROR getting 'android:name' attribute for "
1641bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                                        "meta-data:%s\n", error.string());
1642bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                                goto bail;
16439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
16449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            printf("meta-data: name='%s' ",
16459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    ResTable::normalizeForOutput(metaDataName.string()).string());
16469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            printResolvedResourceAttribute(&res, tree, VALUE_ATTR, String8("value"),
16479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    &error);
16489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (error != "") {
16499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                // Try looking for a RESOURCE_ATTR
16509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                error = "";
16519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                printResolvedResourceAttribute(&res, tree, RESOURCE_ATTR,
16529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                        String8("resource"), &error);
16539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                if (error != "") {
16549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    fprintf(stderr, "ERROR getting 'android:value' or "
16559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                            "'android:resource' attribute for "
16569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                            "meta-data:%s\n", error.string());
16579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    goto bail;
16589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                }
16599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
1660bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                            printf("\n");
16619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        } else if (withinSupportsInput && tag == "input-type") {
16629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            String8 name = getAttribute(tree, NAME_ATTR, &error);
16639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (name != "" && error == "") {
16649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                supportedInput.add(name);
16659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            } else {
16669b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                                fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
16679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                        error.string());
16689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                goto bail;
16699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
16709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
1671bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                    } else if (withinFeatureGroup && tag == "uses-feature") {
16729b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                        FeatureGroup& top = featureGroups.editTop();
16739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
167499a3f3e4e06b4370101ca97cc11dbe81d772fefaWu-cheng Li                        String8 name = getResolvedAttribute(&res, tree, NAME_ATTR, &error);
1675bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                        if (name != "" && error == "") {
16769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            int required = getIntegerAttribute(tree, REQUIRED_ATTR, NULL, 1);
16779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            top.features.add(name, required);
16787005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                            if (required) {
16797005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                                addParentFeatures(&top, name);
16807005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                            }
16817005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala
16827005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                        } else {
16837005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                            int vers = getIntegerAttribute(tree, GL_ES_VERSION_ATTR, &error);
16847005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                            if (error == "") {
16857005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                                if (vers > top.openGLESVersion) {
16867005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                                    top.openGLESVersion = vers;
16877005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                                }
16887005b67c127d229017840925d2bc1bd84c43aaf5Eino-Ville Talvala                            }
16899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
16909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
16919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else if (depth == 4) {
16929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (tag == "intent-filter") {
1693bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                        hasIntentFilter = true;
1694bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                        withinIntentFilter = true;
1695bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                        actMainActivity = false;
1696bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                        actWidgetReceivers = false;
1697bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                        actImeService = false;
16989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        actWallpaperService = false;
16999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        actAccessibilityService = false;
17009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        actPrintService = false;
17019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        actDeviceAdminEnabled = false;
17029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        actHostApduService = false;
17039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        actOffHostApduService = false;
17049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        actDocumentsProvider = false;
17059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        actNotificationListenerService = false;
17069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        actDreamService = false;
17071c04a33c040dfb610952d62da9c93a53c291b2d7Wu-cheng Li                        actCamera = false;
17081c04a33c040dfb610952d62da9c93a53c291b2d7Wu-cheng Li                        actCameraSecure = false;
1709f76a50ce8fdc6aea22cabc77b2977a1a15a79630Ken Wakasa                        catLauncher = false;
17101c04a33c040dfb610952d62da9c93a53c291b2d7Wu-cheng Li                    } else if (withinService && tag == "meta-data") {
17111c04a33c040dfb610952d62da9c93a53c291b2d7Wu-cheng Li                        String8 name = getAttribute(tree, NAME_ATTR, &error);
17121c04a33c040dfb610952d62da9c93a53c291b2d7Wu-cheng Li                        if (error != "") {
17131c04a33c040dfb610952d62da9c93a53c291b2d7Wu-cheng Li                            fprintf(stderr, "ERROR getting 'android:name' attribute for"
17141c04a33c040dfb610952d62da9c93a53c291b2d7Wu-cheng Li                                    " meta-data tag in service '%s': %s\n", serviceName.string(), error.string());
17151c04a33c040dfb610952d62da9c93a53c291b2d7Wu-cheng Li                            goto bail;
17161c04a33c040dfb610952d62da9c93a53c291b2d7Wu-cheng Li                        }
17171c04a33c040dfb610952d62da9c93a53c291b2d7Wu-cheng Li
17181c04a33c040dfb610952d62da9c93a53c291b2d7Wu-cheng Li                        if (name == "android.nfc.cardemulation.host_apdu_service" ||
1719bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                                name == "android.nfc.cardemulation.off_host_apdu_service") {
17209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            bool offHost = true;
17219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (name == "android.nfc.cardemulation.host_apdu_service") {
17229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                offHost = false;
17239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
17249b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li
17259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            String8 xmlPath = getResolvedAttribute(&res, tree, RESOURCE_ATTR, &error);
17269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (error != "") {
17279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                fprintf(stderr, "ERROR getting 'android:resource' attribute for"
17289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                        " meta-data tag in service '%s': %s\n", serviceName.string(), error.string());
17299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                goto bail;
17309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
17319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17324c4300c71229638183d814ab8374e09f722910f5Wu-cheng Li                            Vector<String8> categories = getNfcAidCategories(assets, xmlPath,
17334c4300c71229638183d814ab8374e09f722910f5Wu-cheng Li                                    offHost, &error);
17344c4300c71229638183d814ab8374e09f722910f5Wu-cheng Li                            if (error != "") {
17354c4300c71229638183d814ab8374e09f722910f5Wu-cheng Li                                fprintf(stderr, "ERROR getting AID category for service '%s'\n",
17364c4300c71229638183d814ab8374e09f722910f5Wu-cheng Li                                        serviceName.string());
17374c4300c71229638183d814ab8374e09f722910f5Wu-cheng Li                                goto bail;
17384c4300c71229638183d814ab8374e09f722910f5Wu-cheng Li                            }
17394c4300c71229638183d814ab8374e09f722910f5Wu-cheng Li
17404c4300c71229638183d814ab8374e09f722910f5Wu-cheng Li                            const size_t catLen = categories.size();
17414c4300c71229638183d814ab8374e09f722910f5Wu-cheng Li                            for (size_t i = 0; i < catLen; i++) {
17424c4300c71229638183d814ab8374e09f722910f5Wu-cheng Li                                bool paymentCategory = (categories[i] == "payment");
17434c4300c71229638183d814ab8374e09f722910f5Wu-cheng Li                                if (offHost) {
17444c4300c71229638183d814ab8374e09f722910f5Wu-cheng Li                                    hasMetaOffHostPaymentCategory |= paymentCategory;
17454c4300c71229638183d814ab8374e09f722910f5Wu-cheng Li                                } else {
17464c4300c71229638183d814ab8374e09f722910f5Wu-cheng Li                                    hasMetaHostPaymentCategory |= paymentCategory;
17474c4300c71229638183d814ab8374e09f722910f5Wu-cheng Li                                }
17484c4300c71229638183d814ab8374e09f722910f5Wu-cheng Li                            }
17494c4300c71229638183d814ab8374e09f722910f5Wu-cheng Li                        }
17504c4300c71229638183d814ab8374e09f722910f5Wu-cheng Li                    }
17519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else if ((depth == 5) && withinIntentFilter) {
17529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    String8 action;
17539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (tag == "action") {
17549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        action = getAttribute(tree, NAME_ATTR, &error);
17559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (error != "") {
17569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
17579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    error.string());
175832a972c693400db50717435139fa292a63bc937aEino-Ville Talvala                            goto bail;
175932a972c693400db50717435139fa292a63bc937aEino-Ville Talvala                        }
176032a972c693400db50717435139fa292a63bc937aEino-Ville Talvala
176132a972c693400db50717435139fa292a63bc937aEino-Ville Talvala                        if (withinActivity) {
176232a972c693400db50717435139fa292a63bc937aEino-Ville Talvala                            if (action == "android.intent.action.MAIN") {
176332a972c693400db50717435139fa292a63bc937aEino-Ville Talvala                                isMainActivity = true;
176432a972c693400db50717435139fa292a63bc937aEino-Ville Talvala                                actMainActivity = true;
176532a972c693400db50717435139fa292a63bc937aEino-Ville Talvala                            } else if (action == "android.media.action.STILL_IMAGE_CAMERA" ||
176632a972c693400db50717435139fa292a63bc937aEino-Ville Talvala                                    action == "android.media.action.VIDEO_CAMERA") {
176732a972c693400db50717435139fa292a63bc937aEino-Ville Talvala                                actCamera = true;
176832a972c693400db50717435139fa292a63bc937aEino-Ville Talvala                            } else if (action == "android.media.action.STILL_IMAGE_CAMERA_SECURE") {
176932a972c693400db50717435139fa292a63bc937aEino-Ville Talvala                                actCameraSecure = true;
177032a972c693400db50717435139fa292a63bc937aEino-Ville Talvala                            }
177132a972c693400db50717435139fa292a63bc937aEino-Ville Talvala                        } else if (withinReceiver) {
177232a972c693400db50717435139fa292a63bc937aEino-Ville Talvala                            if (action == "android.appwidget.action.APPWIDGET_UPDATE") {
177332a972c693400db50717435139fa292a63bc937aEino-Ville Talvala                                actWidgetReceivers = true;
177432a972c693400db50717435139fa292a63bc937aEino-Ville Talvala                            } else if (action == "android.app.action.DEVICE_ADMIN_ENABLED") {
177532a972c693400db50717435139fa292a63bc937aEino-Ville Talvala                                actDeviceAdminEnabled = true;
177632a972c693400db50717435139fa292a63bc937aEino-Ville Talvala                            }
177732a972c693400db50717435139fa292a63bc937aEino-Ville Talvala                        } else if (withinService) {
177832a972c693400db50717435139fa292a63bc937aEino-Ville Talvala                            if (action == "android.view.InputMethod") {
177932a972c693400db50717435139fa292a63bc937aEino-Ville Talvala                                actImeService = true;
1780bde61a5731cdfef76a0691f8bd53b880606f5f6eWu-cheng Li                            } else if (action == "android.service.wallpaper.WallpaperService") {
1781bde61a5731cdfef76a0691f8bd53b880606f5f6eWu-cheng Li                                actWallpaperService = true;
1782bde61a5731cdfef76a0691f8bd53b880606f5f6eWu-cheng Li                            } else if (action == "android.accessibilityservice.AccessibilityService") {
1783bde61a5731cdfef76a0691f8bd53b880606f5f6eWu-cheng Li                                actAccessibilityService = true;
1784bde61a5731cdfef76a0691f8bd53b880606f5f6eWu-cheng Li                            } else if (action == "android.printservice.PrintService") {
1785bde61a5731cdfef76a0691f8bd53b880606f5f6eWu-cheng Li                                actPrintService = true;
1786bde61a5731cdfef76a0691f8bd53b880606f5f6eWu-cheng Li                            } else if (action == "android.nfc.cardemulation.action.HOST_APDU_SERVICE") {
178730771b773393596812b6cfd2a4ddf490c43437aaWu-cheng Li                                actHostApduService = true;
178830771b773393596812b6cfd2a4ddf490c43437aaWu-cheng Li                            } else if (action == "android.nfc.cardemulation.action.OFF_HOST_APDU_SERVICE") {
178930771b773393596812b6cfd2a4ddf490c43437aaWu-cheng Li                                actOffHostApduService = true;
179030771b773393596812b6cfd2a4ddf490c43437aaWu-cheng Li                            } else if (action == "android.service.notification.NotificationListenerService") {
179130771b773393596812b6cfd2a4ddf490c43437aaWu-cheng Li                                actNotificationListenerService = true;
179232a972c693400db50717435139fa292a63bc937aEino-Ville Talvala                            } else if (action == "android.service.dreams.DreamService") {
179332a972c693400db50717435139fa292a63bc937aEino-Ville Talvala                                actDreamService = true;
179430771b773393596812b6cfd2a4ddf490c43437aaWu-cheng Li                            }
179530771b773393596812b6cfd2a4ddf490c43437aaWu-cheng Li                        } else if (withinProvider) {
179630771b773393596812b6cfd2a4ddf490c43437aaWu-cheng Li                            if (action == "android.content.action.DOCUMENTS_PROVIDER") {
179730771b773393596812b6cfd2a4ddf490c43437aaWu-cheng Li                                actDocumentsProvider = true;
179830771b773393596812b6cfd2a4ddf490c43437aaWu-cheng Li                            }
179930771b773393596812b6cfd2a4ddf490c43437aaWu-cheng Li                        }
180030771b773393596812b6cfd2a4ddf490c43437aaWu-cheng Li                        if (action == "android.intent.action.SEARCH") {
180130771b773393596812b6cfd2a4ddf490c43437aaWu-cheng Li                            isSearchable = true;
180230771b773393596812b6cfd2a4ddf490c43437aaWu-cheng Li                        }
180330771b773393596812b6cfd2a4ddf490c43437aaWu-cheng Li                    }
180430771b773393596812b6cfd2a4ddf490c43437aaWu-cheng Li
180530771b773393596812b6cfd2a4ddf490c43437aaWu-cheng Li                    if (tag == "category") {
180630771b773393596812b6cfd2a4ddf490c43437aaWu-cheng Li                        String8 category = getAttribute(tree, NAME_ATTR, &error);
180730771b773393596812b6cfd2a4ddf490c43437aaWu-cheng Li                        if (error != "") {
180830771b773393596812b6cfd2a4ddf490c43437aaWu-cheng Li                            fprintf(stderr, "ERROR getting 'name' attribute: %s\n",
180930771b773393596812b6cfd2a4ddf490c43437aaWu-cheng Li                                    error.string());
181030771b773393596812b6cfd2a4ddf490c43437aaWu-cheng Li                            goto bail;
181130771b773393596812b6cfd2a4ddf490c43437aaWu-cheng Li                        }
181230771b773393596812b6cfd2a4ddf490c43437aaWu-cheng Li                        if (withinActivity) {
181330771b773393596812b6cfd2a4ddf490c43437aaWu-cheng Li                            if (category == "android.intent.category.LAUNCHER") {
181430771b773393596812b6cfd2a4ddf490c43437aaWu-cheng Li                                isLauncherActivity = true;
181530771b773393596812b6cfd2a4ddf490c43437aaWu-cheng Li                            } else if (category == "android.intent.category.LEANBACK_LAUNCHER") {
181630771b773393596812b6cfd2a4ddf490c43437aaWu-cheng Li                                isLeanbackLauncherActivity = true;
181730771b773393596812b6cfd2a4ddf490c43437aaWu-cheng Li                            } else if (category == "android.intent.category.HOME") {
181830771b773393596812b6cfd2a4ddf490c43437aaWu-cheng Li                                catLauncher = true;
181930771b773393596812b6cfd2a4ddf490c43437aaWu-cheng Li                            }
1820bde61a5731cdfef76a0691f8bd53b880606f5f6eWu-cheng Li                        }
182132a972c693400db50717435139fa292a63bc937aEino-Ville Talvala                    }
182232a972c693400db50717435139fa292a63bc937aEino-Ville Talvala                }
182332a972c693400db50717435139fa292a63bc937aEino-Ville Talvala            }
182432a972c693400db50717435139fa292a63bc937aEino-Ville Talvala
182532a972c693400db50717435139fa292a63bc937aEino-Ville Talvala            // Pre-1.6 implicitly granted permission compatibility logic
1826bde61a5731cdfef76a0691f8bd53b880606f5f6eWu-cheng Li            if (targetSdk < 4) {
1827bde61a5731cdfef76a0691f8bd53b880606f5f6eWu-cheng Li                if (!hasWriteExternalStoragePermission) {
1828bde61a5731cdfef76a0691f8bd53b880606f5f6eWu-cheng Li                    printUsesPermission(String8("android.permission.WRITE_EXTERNAL_STORAGE"));
1829bde61a5731cdfef76a0691f8bd53b880606f5f6eWu-cheng Li                    printUsesImpliedPermission(String8("android.permission.WRITE_EXTERNAL_STORAGE"),
183030771b773393596812b6cfd2a4ddf490c43437aaWu-cheng Li                            String8("targetSdkVersion < 4"));
183130771b773393596812b6cfd2a4ddf490c43437aaWu-cheng Li                    hasWriteExternalStoragePermission = true;
1832bde61a5731cdfef76a0691f8bd53b880606f5f6eWu-cheng Li                }
183332a972c693400db50717435139fa292a63bc937aEino-Ville Talvala                if (!hasReadPhoneStatePermission) {
183432a972c693400db50717435139fa292a63bc937aEino-Ville Talvala                    printUsesPermission(String8("android.permission.READ_PHONE_STATE"));
183532a972c693400db50717435139fa292a63bc937aEino-Ville Talvala                    printUsesImpliedPermission(String8("android.permission.READ_PHONE_STATE"),
183632a972c693400db50717435139fa292a63bc937aEino-Ville Talvala                            String8("targetSdkVersion < 4"));
183732a972c693400db50717435139fa292a63bc937aEino-Ville Talvala                }
1838bde61a5731cdfef76a0691f8bd53b880606f5f6eWu-cheng Li            }
1839bde61a5731cdfef76a0691f8bd53b880606f5f6eWu-cheng Li
1840bde61a5731cdfef76a0691f8bd53b880606f5f6eWu-cheng Li            // If the application has requested WRITE_EXTERNAL_STORAGE, we will
1841bde61a5731cdfef76a0691f8bd53b880606f5f6eWu-cheng Li            // force them to always take READ_EXTERNAL_STORAGE as well.  We always
184230771b773393596812b6cfd2a4ddf490c43437aaWu-cheng Li            // do this (regardless of target API version) because we can't have
1843bde61a5731cdfef76a0691f8bd53b880606f5f6eWu-cheng Li            // an app with write permission but not read permission.
184430771b773393596812b6cfd2a4ddf490c43437aaWu-cheng Li            if (!hasReadExternalStoragePermission && hasWriteExternalStoragePermission) {
184530771b773393596812b6cfd2a4ddf490c43437aaWu-cheng Li                printUsesPermission(String8("android.permission.READ_EXTERNAL_STORAGE"));
1846bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                printUsesImpliedPermission(String8("android.permission.READ_EXTERNAL_STORAGE"),
18479b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                        String8("requested WRITE_EXTERNAL_STORAGE"));
18489b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            }
1849bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor
1850bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor            // Pre-JellyBean call log permission compatibility.
1851bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor            if (targetSdk < 16) {
1852bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                if (!hasReadCallLogPermission && hasReadContactsPermission) {
18539b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                    printUsesPermission(String8("android.permission.READ_CALL_LOG"));
18549b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                    printUsesImpliedPermission(String8("android.permission.READ_CALL_LOG"),
18559b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                            String8("targetSdkVersion < 16 and requested READ_CONTACTS"));
18569b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                }
1857bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                if (!hasWriteCallLogPermission && hasWriteContactsPermission) {
1858bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                    printUsesPermission(String8("android.permission.WRITE_CALL_LOG"));
1859bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                    printUsesImpliedPermission(String8("android.permission.WRITE_CALL_LOG"),
1860bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor                            String8("targetSdkVersion < 16 and requested WRITE_CONTACTS"));
18619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
18629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
18639b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li
18649b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            addImpliedFeature(&impliedFeatures, "android.hardware.touchscreen",
18659b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                    "default feature for all apps");
18669b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li
1867454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li            const size_t numFeatureGroups = featureGroups.size();
18689b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            if (numFeatureGroups == 0) {
18699b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                // If no <feature-group> tags were defined, apply auto-implied features.
18704c4300c71229638183d814ab8374e09f722910f5Wu-cheng Li                printFeatureGroup(commonFeatures, &impliedFeatures);
18719b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li
18729b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            } else {
18739b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                // <feature-group> tags are defined, so we ignore implied features and
18749b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                for (size_t i = 0; i < numFeatureGroups; i++) {
18759b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                    FeatureGroup& grp = featureGroups.editItemAt(i);
18769b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li
18779b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                    if (commonFeatures.openGLESVersion > grp.openGLESVersion) {
18789b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                        grp.openGLESVersion = commonFeatures.openGLESVersion;
18799b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                    }
1880055c986ab841f8f758398841730f1e90313b132aRay Chen
18819b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                    // Merge the features defined in the top level (not inside a <feature-group>)
18829b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                    // with this feature group.
18839b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                    const size_t numCommonFeatures = commonFeatures.features.size();
18849b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                    for (size_t j = 0; j < numCommonFeatures; j++) {
18859b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                        if (grp.features.indexOfKey(commonFeatures.features.keyAt(j)) < 0) {
188636322db5752c7ec196f59ba94abe5d5a63cc19f5Wu-cheng Li                            grp.features.add(commonFeatures.features.keyAt(j),
188730771b773393596812b6cfd2a4ddf490c43437aaWu-cheng Li                                    commonFeatures.features[j]);
188830771b773393596812b6cfd2a4ddf490c43437aaWu-cheng Li                        }
18896c8d2760736a0753dad96b4bb8f98c7d075e6d54Wu-cheng Li                    }
18906c8d2760736a0753dad96b4bb8f98c7d075e6d54Wu-cheng Li
18916c8d2760736a0753dad96b4bb8f98c7d075e6d54Wu-cheng Li                   if (!grp.features.isEmpty()) {
1892ff723b6c43d5a8fd0ae0e0732f5d47012d74e01dWu-cheng Li                        printFeatureGroup(grp);
189324b326a8978bf78e3e560723dde221792784325bWu-cheng Li                    }
189424b326a8978bf78e3e560723dde221792784325bWu-cheng Li                }
189524b326a8978bf78e3e560723dde221792784325bWu-cheng Li            }
18963773eef4e36fa4171a84b495dca849be112df0a8Eino-Ville Talvala
18973773eef4e36fa4171a84b495dca849be112df0a8Eino-Ville Talvala
1898d9c2601afa46811bcb1345963d38010690981a01Eino-Ville Talvala            if (hasWidgetReceivers) {
1899d9c2601afa46811bcb1345963d38010690981a01Eino-Ville Talvala                printComponentPresence("app-widget");
1900e98e4c806320ccb3078805ac019cca3ed9796123Wu-cheng Li            }
1901e98e4c806320ccb3078805ac019cca3ed9796123Wu-cheng Li            if (hasDeviceAdminReceiver) {
19028cbb8f5e1f939b03515cb4d5942c3fcb226efb9eWu-cheng Li                printComponentPresence("device-admin");
19038cbb8f5e1f939b03515cb4d5942c3fcb226efb9eWu-cheng Li            }
19048cbb8f5e1f939b03515cb4d5942c3fcb226efb9eWu-cheng Li            if (hasImeService) {
19058cbb8f5e1f939b03515cb4d5942c3fcb226efb9eWu-cheng Li                printComponentPresence("ime");
19068cbb8f5e1f939b03515cb4d5942c3fcb226efb9eWu-cheng Li            }
1907e339c5edbebedf446581f18ad70214007309bf4bWu-cheng Li            if (hasWallpaperService) {
1908dd0b16c26834d9a58b9865a467c7a26ea14482f3James Dong                printComponentPresence("wallpaper");
1909dd0b16c26834d9a58b9865a467c7a26ea14482f3James Dong            }
1910dd0b16c26834d9a58b9865a467c7a26ea14482f3James Dong            if (hasAccessibilityService) {
19114c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li                printComponentPresence("accessibility");
19124c2292efbbfe7338138a9a0e8eefeaabdef1a0b4Wu-cheng Li            }
191325d8fb51dae37f1becf4fb3d32e8600c418eb6e8Wu-cheng Li            if (hasPrintService) {
191498bb251c8b527600e7a4cca6cc33499710bbfbf1Wu-cheng Li                printComponentPresence("print-service");
1915037abb8bb064c2878858c9b69978f6754f242627Eino-Ville Talvala            }
1916037abb8bb064c2878858c9b69978f6754f242627Eino-Ville Talvala            if (hasPaymentService) {
1917e339c5edbebedf446581f18ad70214007309bf4bWu-cheng Li                printComponentPresence("payment");
19189b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            }
19199b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            if (isSearchable) {
19209b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                printComponentPresence("search");
19218cbb8f5e1f939b03515cb4d5942c3fcb226efb9eWu-cheng Li            }
19223773eef4e36fa4171a84b495dca849be112df0a8Eino-Ville Talvala            if (hasDocumentsProvider) {
19238cbb8f5e1f939b03515cb4d5942c3fcb226efb9eWu-cheng Li                printComponentPresence("document-provider");
19249b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            }
19259b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            if (hasLauncher) {
19269b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                printComponentPresence("launcher");
19279b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            }
19289b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            if (hasNotificationListenerService) {
19299b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                printComponentPresence("notification-listener");
19309b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            }
19319b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            if (hasDreamService) {
19329b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                printComponentPresence("dream");
19339b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            }
19349b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            if (hasCameraActivity) {
19359b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                printComponentPresence("camera");
19369b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            }
19379b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            if (hasCameraSecureActivity) {
19389b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                printComponentPresence("camera-secure");
19399b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            }
19409b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li
19419b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            if (hasMainActivity) {
19429b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                printf("main\n");
19439b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            }
19449b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            if (hasOtherActivities) {
19459b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                printf("other-activities\n");
19469b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            }
19479b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li             if (hasOtherReceivers) {
19489b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                printf("other-receivers\n");
19499b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            }
19509b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            if (hasOtherServices) {
19519b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                printf("other-services\n");
19529b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            }
19539b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li
19549b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            // For modern apps, if screen size buckets haven't been specified
19559b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            // but the new width ranges have, then infer the buckets from them.
195636f68b8f24df906c969581b0b8e1a47f95dc03cbWu-cheng Li            if (smallScreen > 0 && normalScreen > 0 && largeScreen > 0 && xlargeScreen > 0
19579b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                    && requiresSmallestWidthDp > 0) {
1958068ef42c3ffe1eccec10f97f08541304f679fe67Wu-cheng Li                int compatWidth = compatibleWidthLimitDp;
1959068ef42c3ffe1eccec10f97f08541304f679fe67Wu-cheng Li                if (compatWidth <= 0) {
19609b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                    compatWidth = requiresSmallestWidthDp;
19619b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                }
196236f68b8f24df906c969581b0b8e1a47f95dc03cbWu-cheng Li                if (requiresSmallestWidthDp <= 240 && compatWidth >= 240) {
19639b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                    smallScreen = -1;
1964068ef42c3ffe1eccec10f97f08541304f679fe67Wu-cheng Li                } else {
1965068ef42c3ffe1eccec10f97f08541304f679fe67Wu-cheng Li                    smallScreen = 0;
19669b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                }
19679b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                if (requiresSmallestWidthDp <= 320 && compatWidth >= 320) {
196836f68b8f24df906c969581b0b8e1a47f95dc03cbWu-cheng Li                    normalScreen = -1;
19699b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                } else {
19709b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                    normalScreen = 0;
19719b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                }
19729b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                if (requiresSmallestWidthDp <= 480 && compatWidth >= 480) {
197336f68b8f24df906c969581b0b8e1a47f95dc03cbWu-cheng Li                    largeScreen = -1;
197436322db5752c7ec196f59ba94abe5d5a63cc19f5Wu-cheng Li                } else {
1975068ef42c3ffe1eccec10f97f08541304f679fe67Wu-cheng Li                    largeScreen = 0;
1976068ef42c3ffe1eccec10f97f08541304f679fe67Wu-cheng Li                }
197736322db5752c7ec196f59ba94abe5d5a63cc19f5Wu-cheng Li                if (requiresSmallestWidthDp <= 720 && compatWidth >= 720) {
1978068ef42c3ffe1eccec10f97f08541304f679fe67Wu-cheng Li                    xlargeScreen = -1;
19799b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                } else {
198000e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li                    xlargeScreen = 0;
198100e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li                }
198200e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li            }
19839b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li
198400e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li            // Determine default values for any unspecified screen sizes,
198500e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li            // based on the target SDK of the package.  As of 4 (donut)
198600e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li            // the screen size support was introduced, so all default to
198700e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li            // enabled.
198800e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li            if (smallScreen > 0) {
19899b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                smallScreen = targetSdk >= 4 ? -1 : 0;
199000e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li            }
199100e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li            if (normalScreen > 0) {
199200e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li                normalScreen = -1;
199300e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li            }
19949b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            if (largeScreen > 0) {
199500e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li                largeScreen = targetSdk >= 4 ? -1 : 0;
199600e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li            }
199700e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li            if (xlargeScreen > 0) {
199800e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li                // Introduced in Gingerbread.
19999b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                xlargeScreen = targetSdk >= 9 ? -1 : 0;
200000e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li            }
200100e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li            if (anyDensity > 0) {
200200e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li                anyDensity = (targetSdk >= 4 || requiresSmallestWidthDp > 0
200300e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li                        || compatibleWidthLimitDp > 0) ? -1 : 0;
20049b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            }
200500e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li            printf("supports-screens:");
200600e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li            if (smallScreen != 0) {
200700e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li                printf(" 'small'");
200800e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li            }
20099b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            if (normalScreen != 0) {
201000e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li                printf(" 'normal'");
201100e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li            }
201200e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li            if (largeScreen != 0) {
201300e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li                printf(" 'large'");
20149b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            }
201500e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li            if (xlargeScreen != 0) {
201600e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li                printf(" 'xlarge'");
201700e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li            }
201800e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li            printf("\n");
20199b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            printf("supports-any-density: '%s'\n", anyDensity ? "true" : "false");
202000e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li            if (requiresSmallestWidthDp > 0) {
202100e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li                printf("requires-smallest-width:'%d'\n", requiresSmallestWidthDp);
202200e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li            }
202300e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li            if (compatibleWidthLimitDp > 0) {
20249b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                printf("compatible-width-limit:'%d'\n", compatibleWidthLimitDp);
202500e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li            }
202600e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li            if (largestWidthLimitDp > 0) {
202700e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li                printf("largest-width-limit:'%d'\n", largestWidthLimitDp);
202800e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li            }
20299b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li
203000e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li            printf("locales:");
203100e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li            const size_t NL = locales.size();
203200e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li            for (size_t i=0; i<NL; i++) {
203300e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li                const char* localeStr =  locales[i].string();
20349b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                if (localeStr == NULL || strlen(localeStr) == 0) {
203500e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li                    localeStr = "--_--";
203600e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li                }
203700e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li                printf(" '%s'", localeStr);
203800e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li            }
20399b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            printf("\n");
204000e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li
204100e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li            printf("densities:");
204200e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li            const size_t ND = densities.size();
204300e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li            for (size_t i=0; i<ND; i++) {
204400e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li                printf(" '%d'", densities[i]);
20459b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            }
204600e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li            printf("\n");
204700e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li
204800e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li            AssetDir* dir = assets.openNonAssetDir(assetsCookie, "lib");
204900e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li            if (dir != NULL) {
20509b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                if (dir->getFileCount() > 0) {
205100e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li                    printf("native-code:");
205200e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li                    for (size_t i=0; i<dir->getFileCount(); i++) {
205300e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li                        printf(" '%s'", ResTable::normalizeForOutput(
205400e21f8eb57a7ae2c19516aa0290ab4fb5f251c2Wu-cheng Li                                dir->getFileName(i).string()).string());
20559b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                    }
20569b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                    printf("\n");
2057c58b42327df5fbc826e2fcc2674ab6db0edfcd92Wu-cheng Li                }
2058c58b42327df5fbc826e2fcc2674ab6db0edfcd92Wu-cheng Li                delete dir;
2059c58b42327df5fbc826e2fcc2674ab6db0edfcd92Wu-cheng Li            }
2060c58b42327df5fbc826e2fcc2674ab6db0edfcd92Wu-cheng Li        } else if (strcmp("badger", option) == 0) {
2061c58b42327df5fbc826e2fcc2674ab6db0edfcd92Wu-cheng Li            printf("%s", CONSOLE_DATA);
2062c58b42327df5fbc826e2fcc2674ab6db0edfcd92Wu-cheng Li        } else if (strcmp("configurations", option) == 0) {
206336322db5752c7ec196f59ba94abe5d5a63cc19f5Wu-cheng Li            Vector<ResTable_config> configs;
2064da2f0ea10822628875a956e4bf096066c0debe9fEino-Ville Talvala            res.getConfigurations(&configs);
2065da2f0ea10822628875a956e4bf096066c0debe9fEino-Ville Talvala            const size_t N = configs.size();
2066da2f0ea10822628875a956e4bf096066c0debe9fEino-Ville Talvala            for (size_t i=0; i<N; i++) {
2067da2f0ea10822628875a956e4bf096066c0debe9fEino-Ville Talvala                printf("%s\n", configs[i].toString().string());
2068da2f0ea10822628875a956e4bf096066c0debe9fEino-Ville Talvala            }
2069da2f0ea10822628875a956e4bf096066c0debe9fEino-Ville Talvala        } else {
2070da2f0ea10822628875a956e4bf096066c0debe9fEino-Ville Talvala            fprintf(stderr, "ERROR: unknown dump option '%s'\n", option);
2071da2f0ea10822628875a956e4bf096066c0debe9fEino-Ville Talvala            goto bail;
2072f008f3ea82a0518375ee4ea41b32451badffbd95Wu-cheng Li        }
2073f008f3ea82a0518375ee4ea41b32451badffbd95Wu-cheng Li    }
207436322db5752c7ec196f59ba94abe5d5a63cc19f5Wu-cheng Li
207536322db5752c7ec196f59ba94abe5d5a63cc19f5Wu-cheng Li    result = NO_ERROR;
207636f68b8f24df906c969581b0b8e1a47f95dc03cbWu-cheng Li
207736322db5752c7ec196f59ba94abe5d5a63cc19f5Wu-cheng Libail:
207836322db5752c7ec196f59ba94abe5d5a63cc19f5Wu-cheng Li    if (asset) {
207936322db5752c7ec196f59ba94abe5d5a63cc19f5Wu-cheng Li        delete asset;
208036322db5752c7ec196f59ba94abe5d5a63cc19f5Wu-cheng Li    }
208136322db5752c7ec196f59ba94abe5d5a63cc19f5Wu-cheng Li    return (result != NO_ERROR);
2082f008f3ea82a0518375ee4ea41b32451badffbd95Wu-cheng Li}
2083f008f3ea82a0518375ee4ea41b32451badffbd95Wu-cheng Li
2084f008f3ea82a0518375ee4ea41b32451badffbd95Wu-cheng Li
2085f008f3ea82a0518375ee4ea41b32451badffbd95Wu-cheng Li/*
2086f008f3ea82a0518375ee4ea41b32451badffbd95Wu-cheng Li * Handle the "add" command, which wants to add files to a new or
2087f008f3ea82a0518375ee4ea41b32451badffbd95Wu-cheng Li * pre-existing archive.
208836322db5752c7ec196f59ba94abe5d5a63cc19f5Wu-cheng Li */
208936f68b8f24df906c969581b0b8e1a47f95dc03cbWu-cheng Liint doAdd(Bundle* bundle)
209036322db5752c7ec196f59ba94abe5d5a63cc19f5Wu-cheng Li{
209136322db5752c7ec196f59ba94abe5d5a63cc19f5Wu-cheng Li    ZipFile* zip = NULL;
209236322db5752c7ec196f59ba94abe5d5a63cc19f5Wu-cheng Li    status_t result = UNKNOWN_ERROR;
209336322db5752c7ec196f59ba94abe5d5a63cc19f5Wu-cheng Li    const char* zipFileName;
209436322db5752c7ec196f59ba94abe5d5a63cc19f5Wu-cheng Li
209536322db5752c7ec196f59ba94abe5d5a63cc19f5Wu-cheng Li    if (bundle->getUpdate()) {
209636322db5752c7ec196f59ba94abe5d5a63cc19f5Wu-cheng Li        /* avoid confusion */
209736322db5752c7ec196f59ba94abe5d5a63cc19f5Wu-cheng Li        fprintf(stderr, "ERROR: can't use '-u' with add\n");
2098c58b42327df5fbc826e2fcc2674ab6db0edfcd92Wu-cheng Li        goto bail;
2099c58b42327df5fbc826e2fcc2674ab6db0edfcd92Wu-cheng Li    }
2100c58b42327df5fbc826e2fcc2674ab6db0edfcd92Wu-cheng Li
2101c58b42327df5fbc826e2fcc2674ab6db0edfcd92Wu-cheng Li    if (bundle->getFileSpecCount() < 1) {
2102c58b42327df5fbc826e2fcc2674ab6db0edfcd92Wu-cheng Li        fprintf(stderr, "ERROR: must specify zip file name\n");
2103c58b42327df5fbc826e2fcc2674ab6db0edfcd92Wu-cheng Li        goto bail;
2104c58b42327df5fbc826e2fcc2674ab6db0edfcd92Wu-cheng Li    }
2105699fe9397974685e6b2c73f9a3a0eb9e5a5a2ccfWu-cheng Li    zipFileName = bundle->getFileSpecEntry(0);
2106d45cb72ac0d7d57829ffc9223decb89a5fc42ce2Wu-cheng Li
2107b9ac75d3dfc53ab4a0a104da147f1dfd7bc8c12fWu-cheng Li    if (bundle->getFileSpecCount() < 2) {
2108b9ac75d3dfc53ab4a0a104da147f1dfd7bc8c12fWu-cheng Li        fprintf(stderr, "NOTE: nothing to do\n");
2109b9ac75d3dfc53ab4a0a104da147f1dfd7bc8c12fWu-cheng Li        goto bail;
2110b9ac75d3dfc53ab4a0a104da147f1dfd7bc8c12fWu-cheng Li    }
2111b9ac75d3dfc53ab4a0a104da147f1dfd7bc8c12fWu-cheng Li
211253b30912d3e8598c05e47308981971e958e98db2Wu-cheng Li    zip = openReadWrite(zipFileName, true);
211353b30912d3e8598c05e47308981971e958e98db2Wu-cheng Li    if (zip == NULL) {
211453b30912d3e8598c05e47308981971e958e98db2Wu-cheng Li        fprintf(stderr, "ERROR: failed opening/creating '%s' as Zip file\n", zipFileName);
211553b30912d3e8598c05e47308981971e958e98db2Wu-cheng Li        goto bail;
211653b30912d3e8598c05e47308981971e958e98db2Wu-cheng Li    }
211753b30912d3e8598c05e47308981971e958e98db2Wu-cheng Li
211853b30912d3e8598c05e47308981971e958e98db2Wu-cheng Li    for (int i = 1; i < bundle->getFileSpecCount(); i++) {
211953b30912d3e8598c05e47308981971e958e98db2Wu-cheng Li        const char* fileName = bundle->getFileSpecEntry(i);
212053b30912d3e8598c05e47308981971e958e98db2Wu-cheng Li
212153b30912d3e8598c05e47308981971e958e98db2Wu-cheng Li        if (strcasecmp(String8(fileName).getPathExtension().string(), ".gz") == 0) {
212253b30912d3e8598c05e47308981971e958e98db2Wu-cheng Li            printf(" '%s'... (from gzip)\n", fileName);
212353b30912d3e8598c05e47308981971e958e98db2Wu-cheng Li            result = zip->addGzip(fileName, String8(fileName).getBasePath().string(), NULL);
2124d45cb72ac0d7d57829ffc9223decb89a5fc42ce2Wu-cheng Li        } else {
2125d45cb72ac0d7d57829ffc9223decb89a5fc42ce2Wu-cheng Li            if (bundle->getJunkPath()) {
2126699fe9397974685e6b2c73f9a3a0eb9e5a5a2ccfWu-cheng Li                String8 storageName = String8(fileName).getPathLeaf();
2127b9ac75d3dfc53ab4a0a104da147f1dfd7bc8c12fWu-cheng Li                printf(" '%s' as '%s'...\n", fileName,
2128b9ac75d3dfc53ab4a0a104da147f1dfd7bc8c12fWu-cheng Li                        ResTable::normalizeForOutput(storageName.string()).string());
2129b9ac75d3dfc53ab4a0a104da147f1dfd7bc8c12fWu-cheng Li                result = zip->add(fileName, storageName.string(),
2130b9ac75d3dfc53ab4a0a104da147f1dfd7bc8c12fWu-cheng Li                                  bundle->getCompressionMethod(), NULL);
213153b30912d3e8598c05e47308981971e958e98db2Wu-cheng Li            } else {
213253b30912d3e8598c05e47308981971e958e98db2Wu-cheng Li                printf(" '%s'...\n", fileName);
21330f4f97b70f6ad59b32e78720ba7357733bdef3e9Wu-cheng Li                result = zip->add(fileName, bundle->getCompressionMethod(), NULL);
21340f4f97b70f6ad59b32e78720ba7357733bdef3e9Wu-cheng Li            }
21350f4f97b70f6ad59b32e78720ba7357733bdef3e9Wu-cheng Li        }
21360f4f97b70f6ad59b32e78720ba7357733bdef3e9Wu-cheng Li        if (result != NO_ERROR) {
21370f4f97b70f6ad59b32e78720ba7357733bdef3e9Wu-cheng Li            fprintf(stderr, "Unable to add '%s' to '%s'", bundle->getFileSpecEntry(i), zipFileName);
21380f4f97b70f6ad59b32e78720ba7357733bdef3e9Wu-cheng Li            if (result == NAME_NOT_FOUND) {
21390f4f97b70f6ad59b32e78720ba7357733bdef3e9Wu-cheng Li                fprintf(stderr, ": file not found\n");
21400f4f97b70f6ad59b32e78720ba7357733bdef3e9Wu-cheng Li            } else if (result == ALREADY_EXISTS) {
21410f4f97b70f6ad59b32e78720ba7357733bdef3e9Wu-cheng Li                fprintf(stderr, ": already exists in archive\n");
21420f4f97b70f6ad59b32e78720ba7357733bdef3e9Wu-cheng Li            } else {
21430f4f97b70f6ad59b32e78720ba7357733bdef3e9Wu-cheng Li                fprintf(stderr, "\n");
21440f4f97b70f6ad59b32e78720ba7357733bdef3e9Wu-cheng Li            }
2145b9ac75d3dfc53ab4a0a104da147f1dfd7bc8c12fWu-cheng Li            goto bail;
2146b9ac75d3dfc53ab4a0a104da147f1dfd7bc8c12fWu-cheng Li        }
2147b9ac75d3dfc53ab4a0a104da147f1dfd7bc8c12fWu-cheng Li    }
2148b9ac75d3dfc53ab4a0a104da147f1dfd7bc8c12fWu-cheng Li
2149b9ac75d3dfc53ab4a0a104da147f1dfd7bc8c12fWu-cheng Li    result = NO_ERROR;
2150e339c5edbebedf446581f18ad70214007309bf4bWu-cheng Li
2151e339c5edbebedf446581f18ad70214007309bf4bWu-cheng Libail:
2152e339c5edbebedf446581f18ad70214007309bf4bWu-cheng Li    delete zip;
2153e339c5edbebedf446581f18ad70214007309bf4bWu-cheng Li    return (result != NO_ERROR);
2154e339c5edbebedf446581f18ad70214007309bf4bWu-cheng Li}
2155e339c5edbebedf446581f18ad70214007309bf4bWu-cheng Li
2156e339c5edbebedf446581f18ad70214007309bf4bWu-cheng Li
2157e339c5edbebedf446581f18ad70214007309bf4bWu-cheng Li/*
2158e339c5edbebedf446581f18ad70214007309bf4bWu-cheng Li * Delete files from an existing archive.
2159e339c5edbebedf446581f18ad70214007309bf4bWu-cheng Li */
2160e339c5edbebedf446581f18ad70214007309bf4bWu-cheng Liint doRemove(Bundle* bundle)
2161e339c5edbebedf446581f18ad70214007309bf4bWu-cheng Li{
2162e339c5edbebedf446581f18ad70214007309bf4bWu-cheng Li    ZipFile* zip = NULL;
2163e339c5edbebedf446581f18ad70214007309bf4bWu-cheng Li    status_t result = UNKNOWN_ERROR;
2164e339c5edbebedf446581f18ad70214007309bf4bWu-cheng Li    const char* zipFileName;
2165e339c5edbebedf446581f18ad70214007309bf4bWu-cheng Li
2166e339c5edbebedf446581f18ad70214007309bf4bWu-cheng Li    if (bundle->getFileSpecCount() < 1) {
2167e339c5edbebedf446581f18ad70214007309bf4bWu-cheng Li        fprintf(stderr, "ERROR: must specify zip file name\n");
2168e339c5edbebedf446581f18ad70214007309bf4bWu-cheng Li        goto bail;
2169ca099614841bc619f217dfa088da630a7eb1ab65Wu-cheng Li    }
2170454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    zipFileName = bundle->getFileSpecEntry(0);
2171454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li
2172454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    if (bundle->getFileSpecCount() < 2) {
2173454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li        fprintf(stderr, "NOTE: nothing to do\n");
2174454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li        goto bail;
2175454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    }
2176454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li
2177454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    zip = openReadWrite(zipFileName, false);
2178454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    if (zip == NULL) {
2179454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li        fprintf(stderr, "ERROR: failed opening Zip archive '%s'\n",
2180454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li            zipFileName);
2181454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li        goto bail;
2182454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    }
21839b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li
21849b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    for (int i = 1; i < bundle->getFileSpecCount(); i++) {
21859b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li        const char* fileName = bundle->getFileSpecEntry(i);
2186eb68c46a40c773eb56ef7bcf8e7ece5c6a5a8d23Chih-Chung Chang        ZipEntry* entry;
218710a1b30dfbd0bbeae6776e353600986647c6e0a8Wu-cheng Li
21889b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li        entry = zip->getEntryByName(fileName);
21899b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li        if (entry == NULL) {
219070fb9085044c5e6f52c33c970d238b764cf2373bWu-cheng Li            printf(" '%s' NOT FOUND\n", fileName);
21919b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            continue;
21927d9a8ffd08fa950eb14f8224f6090fe46ab4aa9fIgor Murashkin        }
21937d9a8ffd08fa950eb14f8224f6090fe46ab4aa9fIgor Murashkin
21947d9a8ffd08fa950eb14f8224f6090fe46ab4aa9fIgor Murashkin        result = zip->remove(entry);
21957d9a8ffd08fa950eb14f8224f6090fe46ab4aa9fIgor Murashkin
21967d9a8ffd08fa950eb14f8224f6090fe46ab4aa9fIgor Murashkin        if (result != NO_ERROR) {
21977d9a8ffd08fa950eb14f8224f6090fe46ab4aa9fIgor Murashkin            fprintf(stderr, "Unable to delete '%s' from '%s'\n",
21987d9a8ffd08fa950eb14f8224f6090fe46ab4aa9fIgor Murashkin                bundle->getFileSpecEntry(i), zipFileName);
21997d9a8ffd08fa950eb14f8224f6090fe46ab4aa9fIgor Murashkin            goto bail;
22007d9a8ffd08fa950eb14f8224f6090fe46ab4aa9fIgor Murashkin        }
22017d9a8ffd08fa950eb14f8224f6090fe46ab4aa9fIgor Murashkin    }
22027d9a8ffd08fa950eb14f8224f6090fe46ab4aa9fIgor Murashkin
22039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* update the archive */
22049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    zip->flush();
22057d9a8ffd08fa950eb14f8224f6090fe46ab4aa9fIgor Murashkin
22069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbail:
22079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    delete zip;
22089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return (result != NO_ERROR);
22099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
22109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
22119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic status_t addResourcesToBuilder(const sp<AaptDir>& dir, const sp<ApkBuilder>& builder, bool ignoreConfig=false) {
22129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const size_t numDirs = dir->getDirs().size();
22139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (size_t i = 0; i < numDirs; i++) {
22149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bool ignore = ignoreConfig;
22159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const sp<AaptDir>& subDir = dir->getDirs().valueAt(i);
22169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const char* dirStr = subDir->getLeaf().string();
22179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!ignore && strstr(dirStr, "mipmap") == dirStr) {
22189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ignore = true;
22199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
22209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        status_t err = addResourcesToBuilder(subDir, builder, ignore);
22219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (err != NO_ERROR) {
22229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return err;
22239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
22249b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    }
22259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
22269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const size_t numFiles = dir->getFiles().size();
22279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (size_t i = 0; i < numFiles; i++) {
22289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sp<AaptGroup> gp = dir->getFiles().valueAt(i);
22290a12018e4cd6eaaeaec795f6b2af4499fe3a8bcdAli Utku Selen        const size_t numConfigs = gp->getFiles().size();
22309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (size_t j = 0; j < numConfigs; j++) {
22319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            status_t err = NO_ERROR;
22329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (ignoreConfig) {
22339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                err = builder->getBaseSplit()->addEntry(gp->getPath(), gp->getFiles().valueAt(j));
22349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
22359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                err = builder->addEntry(gp->getPath(), gp->getFiles().valueAt(j));
22369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
22379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (err != NO_ERROR) {
22389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                fprintf(stderr, "Failed to add %s (%s) to builder.\n",
22399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        gp->getPath().string(), gp->getFiles()[j]->getPrintableSource().string());
22409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return err;
22419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
22429b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li        }
22439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
22449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return NO_ERROR;
22459b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li}
22469b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li
22479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic String8 buildApkName(const String8& original, const sp<ApkSplit>& split) {
22489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (split->isBase()) {
22499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return original;
22509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
22519b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li
22520a12018e4cd6eaaeaec795f6b2af4499fe3a8bcdAli Utku Selen    String8 ext(original.getPathExtension());
22530a12018e4cd6eaaeaec795f6b2af4499fe3a8bcdAli Utku Selen    if (ext == String8(".apk")) {
22540a12018e4cd6eaaeaec795f6b2af4499fe3a8bcdAli Utku Selen        return String8::format("%s_%s%s",
22559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                original.getBasePath().string(),
22569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                split->getDirectorySafeName().string(),
22579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ext.string());
22589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
22599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
22609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return String8::format("%s_%s", original.string(),
22619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            split->getDirectorySafeName().string());
22629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
22639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
22649b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li/*
22659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Package up an asset directory and associated application files.
22669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
22679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint doPackage(Bundle* bundle)
22689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
22699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char* outputAPKFile;
22709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int retVal = 1;
22719b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    status_t err;
22729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sp<AaptAssets> assets;
22739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int N;
22749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FILE* fp;
22759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String8 dependencyFile;
2276cb56923ba6350cf7441260886f6e8a1c6785886dEino-Ville Talvala    sp<ApkBuilder> builder;
2277cb56923ba6350cf7441260886f6e8a1c6785886dEino-Ville Talvala
22789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // -c en_XA or/and ar_XB means do pseudolocalization
22799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sp<WeakResourceFilter> configFilter = new WeakResourceFilter();
2280cb56923ba6350cf7441260886f6e8a1c6785886dEino-Ville Talvala    err = configFilter->parse(bundle->getConfigurations());
2281cb56923ba6350cf7441260886f6e8a1c6785886dEino-Ville Talvala    if (err != NO_ERROR) {
22829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto bail;
22839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
22849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (configFilter->containsPseudo()) {
22857d9a8ffd08fa950eb14f8224f6090fe46ab4aa9fIgor Murashkin        bundle->setPseudolocalize(bundle->getPseudolocalize() | PSEUDO_ACCENTED);
22869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
22879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (configFilter->containsPseudoBidi()) {
22889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bundle->setPseudolocalize(bundle->getPseudolocalize() | PSEUDO_BIDI);
22899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
22909b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li
22919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    N = bundle->getFileSpecCount();
22929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (N < 1 && bundle->getResourceSourceDirs().size() == 0 && bundle->getJarFiles().size() == 0
22939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            && bundle->getAndroidManifestFile() == NULL && bundle->getAssetSourceDirs().size() == 0) {
22949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "ERROR: no input files\n");
22957d9a8ffd08fa950eb14f8224f6090fe46ab4aa9fIgor Murashkin        goto bail;
22967d9a8ffd08fa950eb14f8224f6090fe46ab4aa9fIgor Murashkin    }
22977d9a8ffd08fa950eb14f8224f6090fe46ab4aa9fIgor Murashkin
22987d9a8ffd08fa950eb14f8224f6090fe46ab4aa9fIgor Murashkin    outputAPKFile = bundle->getOutputAPKFile();
22997d9a8ffd08fa950eb14f8224f6090fe46ab4aa9fIgor Murashkin
23007d9a8ffd08fa950eb14f8224f6090fe46ab4aa9fIgor Murashkin    // Make sure the filenames provided exist and are of the appropriate type.
23017d9a8ffd08fa950eb14f8224f6090fe46ab4aa9fIgor Murashkin    if (outputAPKFile) {
23027d9a8ffd08fa950eb14f8224f6090fe46ab4aa9fIgor Murashkin        FileType type;
23037d9a8ffd08fa950eb14f8224f6090fe46ab4aa9fIgor Murashkin        type = getFileType(outputAPKFile);
23047d9a8ffd08fa950eb14f8224f6090fe46ab4aa9fIgor Murashkin        if (type != kFileTypeNonexistent && type != kFileTypeRegular) {
23057d9a8ffd08fa950eb14f8224f6090fe46ab4aa9fIgor Murashkin            fprintf(stderr,
23067d9a8ffd08fa950eb14f8224f6090fe46ab4aa9fIgor Murashkin                "ERROR: output file '%s' exists but is not regular file\n",
23079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                outputAPKFile);
23089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
2309e98e4c806320ccb3078805ac019cca3ed9796123Wu-cheng Li        }
2310f715bf95ded30821e81ba93bb48c08725e1c34aaWu-cheng Li    }
2311f715bf95ded30821e81ba93bb48c08725e1c34aaWu-cheng Li
2312f715bf95ded30821e81ba93bb48c08725e1c34aaWu-cheng Li    // Load the assets.
2313f715bf95ded30821e81ba93bb48c08725e1c34aaWu-cheng Li    assets = new AaptAssets();
2314f715bf95ded30821e81ba93bb48c08725e1c34aaWu-cheng Li
2315f715bf95ded30821e81ba93bb48c08725e1c34aaWu-cheng Li    // Set up the resource gathering in assets if we're going to generate
2316f715bf95ded30821e81ba93bb48c08725e1c34aaWu-cheng Li    // dependency files. Every time we encounter a resource while slurping
2317f715bf95ded30821e81ba93bb48c08725e1c34aaWu-cheng Li    // the tree, we'll add it to these stores so we have full resource paths
2318f715bf95ded30821e81ba93bb48c08725e1c34aaWu-cheng Li    // to write to a dependency file.
2319f715bf95ded30821e81ba93bb48c08725e1c34aaWu-cheng Li    if (bundle->getGenDependencies()) {
2320f715bf95ded30821e81ba93bb48c08725e1c34aaWu-cheng Li        sp<FilePathStore> resPathStore = new FilePathStore;
2321f715bf95ded30821e81ba93bb48c08725e1c34aaWu-cheng Li        assets->setFullResPaths(resPathStore);
2322f715bf95ded30821e81ba93bb48c08725e1c34aaWu-cheng Li        sp<FilePathStore> assetPathStore = new FilePathStore;
2323f715bf95ded30821e81ba93bb48c08725e1c34aaWu-cheng Li        assets->setFullAssetPaths(assetPathStore);
2324f715bf95ded30821e81ba93bb48c08725e1c34aaWu-cheng Li    }
2325f715bf95ded30821e81ba93bb48c08725e1c34aaWu-cheng Li
2326f715bf95ded30821e81ba93bb48c08725e1c34aaWu-cheng Li    err = assets->slurpFromArgs(bundle);
2327f715bf95ded30821e81ba93bb48c08725e1c34aaWu-cheng Li    if (err < 0) {
2328f715bf95ded30821e81ba93bb48c08725e1c34aaWu-cheng Li        goto bail;
2329f715bf95ded30821e81ba93bb48c08725e1c34aaWu-cheng Li    }
2330f715bf95ded30821e81ba93bb48c08725e1c34aaWu-cheng Li
2331e98e4c806320ccb3078805ac019cca3ed9796123Wu-cheng Li    if (bundle->getVerbose()) {
2332e98e4c806320ccb3078805ac019cca3ed9796123Wu-cheng Li        assets->print(String8());
2333e98e4c806320ccb3078805ac019cca3ed9796123Wu-cheng Li    }
23349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
23359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Create the ApkBuilder, which will collect the compiled files
23369b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    // to write to the final APK (or sets of APKs if we are building
23379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // a Split APK.
23389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    builder = new ApkBuilder(configFilter);
23399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
23409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // If we are generating a Split APK, find out which configurations to split on.
23419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (bundle->getSplitConfigurations().size() > 0) {
23429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const Vector<String8>& splitStrs = bundle->getSplitConfigurations();
23439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const size_t numSplits = splitStrs.size();
23449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (size_t i = 0; i < numSplits; i++) {
23459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            std::set<ConfigDescription> configs;
23469b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            if (!AaptConfig::parseCommaSeparatedList(splitStrs[i], &configs)) {
23479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                fprintf(stderr, "ERROR: failed to parse split configuration '%s'\n", splitStrs[i].string());
23489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                goto bail;
23499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
23509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
23519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            err = builder->createSplitForConfigs(configs);
23529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (err != NO_ERROR) {
23539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                goto bail;
23549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
235526274fae33b7b056cf5fe9fd6e823cae9e4ddae2Wu-cheng Li        }
235626274fae33b7b056cf5fe9fd6e823cae9e4ddae2Wu-cheng Li    }
235726274fae33b7b056cf5fe9fd6e823cae9e4ddae2Wu-cheng Li
23589b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    // If they asked for any fileAs that need to be compiled, do so.
2359c157e0cd161e5b3b28b72bafebb3360ed856a608Wu-cheng Li    if (bundle->getResourceSourceDirs().size() || bundle->getAndroidManifestFile()) {
2360c157e0cd161e5b3b28b72bafebb3360ed856a608Wu-cheng Li        err = buildResources(bundle, assets, builder);
2361c157e0cd161e5b3b28b72bafebb3360ed856a608Wu-cheng Li        if (err != 0) {
2362c157e0cd161e5b3b28b72bafebb3360ed856a608Wu-cheng Li            goto bail;
2363c157e0cd161e5b3b28b72bafebb3360ed856a608Wu-cheng Li        }
2364c157e0cd161e5b3b28b72bafebb3360ed856a608Wu-cheng Li    }
2365c157e0cd161e5b3b28b72bafebb3360ed856a608Wu-cheng Li
2366c157e0cd161e5b3b28b72bafebb3360ed856a608Wu-cheng Li    // At this point we've read everything and processed everything.  From here
2367c157e0cd161e5b3b28b72bafebb3360ed856a608Wu-cheng Li    // on out it's just writing output files.
2368c157e0cd161e5b3b28b72bafebb3360ed856a608Wu-cheng Li    if (SourcePos::hasErrors()) {
2369c157e0cd161e5b3b28b72bafebb3360ed856a608Wu-cheng Li        goto bail;
23709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
23719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2372c157e0cd161e5b3b28b72bafebb3360ed856a608Wu-cheng Li    // Update symbols with information about which ones are needed as Java symbols.
2373c157e0cd161e5b3b28b72bafebb3360ed856a608Wu-cheng Li    assets->applyJavaSymbols();
2374c157e0cd161e5b3b28b72bafebb3360ed856a608Wu-cheng Li    if (SourcePos::hasErrors()) {
2375c157e0cd161e5b3b28b72bafebb3360ed856a608Wu-cheng Li        goto bail;
23769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
23779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
23789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // If we've been asked to generate a dependency file, do that here
23799b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    if (bundle->getGenDependencies()) {
23809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // If this is the packaging step, generate the dependency file next to
23819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // the output apk (e.g. bin/resources.ap_.d)
23829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (outputAPKFile) {
23839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            dependencyFile = String8(outputAPKFile);
23849b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            // Add the .d extension to the dependency file.
2385dd0b16c26834d9a58b9865a467c7a26ea14482f3James Dong            dependencyFile.append(".d");
23869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
23879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Else if this is the R.java dependency generation step,
23889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // generate the dependency file in the R.java package subdirectory
23899b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            // e.g. gen/com/foo/app/R.java.d
23909b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            dependencyFile = String8(bundle->getRClassDir());
23919b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            dependencyFile.appendPath("R.java.d");
23929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
23939b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li        // Make sure we have a clean dependency file to start with
23949b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li        fp = fopen(dependencyFile, "w");
23959b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li        fclose(fp);
23963f4639a6611222ae1ae5493de49213250d292139Wu-cheng Li    }
23979c79938d47a3caa06e5fb956955374f30c55992bWu-cheng Li
23989b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    // Write out R.java constants
23999b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    if (!assets->havePrivateSymbols()) {
24009b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li        if (bundle->getCustomPackage() == NULL) {
24019b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            // Write the R.java file into the appropriate class directory
24029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // e.g. gen/com/foo/app/R.java
24039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            err = writeResourceSymbols(bundle, assets, assets->getPackage(), true);
24049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
240532a972c693400db50717435139fa292a63bc937aEino-Ville Talvala            const String8 customPkg(bundle->getCustomPackage());
240632a972c693400db50717435139fa292a63bc937aEino-Ville Talvala            err = writeResourceSymbols(bundle, assets, customPkg, true);
2407dd0b16c26834d9a58b9865a467c7a26ea14482f3James Dong        }
240832a972c693400db50717435139fa292a63bc937aEino-Ville Talvala        if (err < 0) {
2409dd0b16c26834d9a58b9865a467c7a26ea14482f3James Dong            goto bail;
2410dd0b16c26834d9a58b9865a467c7a26ea14482f3James Dong        }
2411dd0b16c26834d9a58b9865a467c7a26ea14482f3James Dong        // If we have library files, we're going to write our R.java file into
2412dd0b16c26834d9a58b9865a467c7a26ea14482f3James Dong        // the appropriate class directory for those libraries as well.
241332a972c693400db50717435139fa292a63bc937aEino-Ville Talvala        // e.g. gen/com/foo/app/lib/R.java
2414dd0b16c26834d9a58b9865a467c7a26ea14482f3James Dong        if (bundle->getExtraPackages() != NULL) {
2415dd0b16c26834d9a58b9865a467c7a26ea14482f3James Dong            // Split on colon
2416dd0b16c26834d9a58b9865a467c7a26ea14482f3James Dong            String8 libs(bundle->getExtraPackages());
2417dd0b16c26834d9a58b9865a467c7a26ea14482f3James Dong            char* packageString = strtok(libs.lockBuffer(libs.length()), ":");
2418dd0b16c26834d9a58b9865a467c7a26ea14482f3James Dong            while (packageString != NULL) {
2419dd0b16c26834d9a58b9865a467c7a26ea14482f3James Dong                // Write the R.java file out with the correct package name
2420dd0b16c26834d9a58b9865a467c7a26ea14482f3James Dong                err = writeResourceSymbols(bundle, assets, String8(packageString), true);
2421dd0b16c26834d9a58b9865a467c7a26ea14482f3James Dong                if (err < 0) {
2422dd0b16c26834d9a58b9865a467c7a26ea14482f3James Dong                    goto bail;
2423dd0b16c26834d9a58b9865a467c7a26ea14482f3James Dong                }
2424dd0b16c26834d9a58b9865a467c7a26ea14482f3James Dong                packageString = strtok(NULL, ":");
2425dd0b16c26834d9a58b9865a467c7a26ea14482f3James Dong            }
2426dd0b16c26834d9a58b9865a467c7a26ea14482f3James Dong            libs.unlockBuffer();
2427dd0b16c26834d9a58b9865a467c7a26ea14482f3James Dong        }
2428dd0b16c26834d9a58b9865a467c7a26ea14482f3James Dong    } else {
2429dd0b16c26834d9a58b9865a467c7a26ea14482f3James Dong        err = writeResourceSymbols(bundle, assets, assets->getPackage(), false);
2430dd0b16c26834d9a58b9865a467c7a26ea14482f3James Dong        if (err < 0) {
2431dd0b16c26834d9a58b9865a467c7a26ea14482f3James Dong            goto bail;
2432dd0b16c26834d9a58b9865a467c7a26ea14482f3James Dong        }
2433dd0b16c26834d9a58b9865a467c7a26ea14482f3James Dong        err = writeResourceSymbols(bundle, assets, assets->getSymbolsPrivatePackage(), true);
2434dd0b16c26834d9a58b9865a467c7a26ea14482f3James Dong        if (err < 0) {
2435dd0b16c26834d9a58b9865a467c7a26ea14482f3James Dong            goto bail;
2436dd0b16c26834d9a58b9865a467c7a26ea14482f3James Dong        }
2437dd0b16c26834d9a58b9865a467c7a26ea14482f3James Dong    }
2438dd0b16c26834d9a58b9865a467c7a26ea14482f3James Dong
2439dd0b16c26834d9a58b9865a467c7a26ea14482f3James Dong    // Write out the ProGuard file
2440dd0b16c26834d9a58b9865a467c7a26ea14482f3James Dong    err = writeProguardFile(bundle, assets);
2441dd0b16c26834d9a58b9865a467c7a26ea14482f3James Dong    if (err < 0) {
2442dd0b16c26834d9a58b9865a467c7a26ea14482f3James Dong        goto bail;
2443dd0b16c26834d9a58b9865a467c7a26ea14482f3James Dong    }
2444dd0b16c26834d9a58b9865a467c7a26ea14482f3James Dong
244532a972c693400db50717435139fa292a63bc937aEino-Ville Talvala    // Write the apk
24464c4300c71229638183d814ab8374e09f722910f5Wu-cheng Li    if (outputAPKFile) {
244732a972c693400db50717435139fa292a63bc937aEino-Ville Talvala        // Gather all resources and add them to the APK Builder. The builder will then
24489b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li        // figure out which Split they belong in.
244932a972c693400db50717435139fa292a63bc937aEino-Ville Talvala        err = addResourcesToBuilder(assets, builder);
245032a972c693400db50717435139fa292a63bc937aEino-Ville Talvala        if (err != NO_ERROR) {
2451c157e0cd161e5b3b28b72bafebb3360ed856a608Wu-cheng Li            goto bail;
24529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
24539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2454c157e0cd161e5b3b28b72bafebb3360ed856a608Wu-cheng Li        const Vector<sp<ApkSplit> >& splits = builder->getSplits();
24559b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li        const size_t numSplits = splits.size();
24569b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li        for (size_t i = 0; i < numSplits; i++) {
24579b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            const sp<ApkSplit>& split = splits[i];
24589b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            String8 outputPath = buildApkName(String8(outputAPKFile), split);
24599b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            err = writeAPK(bundle, outputPath, split);
24609b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li            if (err != NO_ERROR) {
24619b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                fprintf(stderr, "ERROR: packaging of '%s' failed\n", outputPath.string());
24629b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li                goto bail;
24639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
24649b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li        }
24659b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    }
24669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
24679b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    // If we've been asked to generate a dependency file, we need to finish up here.
24689b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    // the writeResourceSymbols and writeAPK functions have already written the target
24699b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    // half of the dependency file, now we need to write the prerequisites. (files that
24709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // the R.java file or .ap_ file depend on)
24719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (bundle->getGenDependencies()) {
24729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Now that writeResourceSymbols or writeAPK has taken care of writing
24734c4300c71229638183d814ab8374e09f722910f5Wu-cheng Li        // the targets to our dependency file, we'll write the prereqs
24744c4300c71229638183d814ab8374e09f722910f5Wu-cheng Li        fp = fopen(dependencyFile, "a+");
24753f4639a6611222ae1ae5493de49213250d292139Wu-cheng Li        fprintf(fp, " : ");
24764c4300c71229638183d814ab8374e09f722910f5Wu-cheng Li        bool includeRaw = (outputAPKFile != NULL);
24774c4300c71229638183d814ab8374e09f722910f5Wu-cheng Li        err = writeDependencyPreReqs(bundle, assets, fp, includeRaw);
24784c4300c71229638183d814ab8374e09f722910f5Wu-cheng Li        // Also manually add the AndroidManifeset since it's not under res/ or assets/
24794c4300c71229638183d814ab8374e09f722910f5Wu-cheng Li        // and therefore was not added to our pathstores during slurping
24804c4300c71229638183d814ab8374e09f722910f5Wu-cheng Li        fprintf(fp, "%s \\\n", bundle->getAndroidManifestFile());
24814c4300c71229638183d814ab8374e09f722910f5Wu-cheng Li        fclose(fp);
24824c4300c71229638183d814ab8374e09f722910f5Wu-cheng Li    }
24834c4300c71229638183d814ab8374e09f722910f5Wu-cheng Li
24844c4300c71229638183d814ab8374e09f722910f5Wu-cheng Li    retVal = 0;
24859b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Libail:
24869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (SourcePos::hasErrors()) {
24879b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li        SourcePos::printErrors(stderr);
24889b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    }
24899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return retVal;
24909b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li}
24919b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li
24929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
24939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Do PNG Crunching
24949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * PRECONDITIONS
24959b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li *  -S flag points to a source directory containing drawable* folders
24969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *  -C flag points to destination directory. The folder structure in the
24979b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li *     source directory will be mirrored to the destination (cache) directory
24989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
24999b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li * POSTCONDITIONS
25009b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li *  Destination directory will be updated to match the PNG files in
25019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *  the source directory.
25029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
25039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint doCrunch(Bundle* bundle)
25049b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li{
25059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    fprintf(stdout, "Crunching PNG Files in ");
25069b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    fprintf(stdout, "source dir: %s\n", bundle->getResourceSourceDirs()[0]);
25079b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    fprintf(stdout, "To destination dir: %s\n", bundle->getCrunchedOutputDir());
25089b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li
25099b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    updatePreProcessedCache(bundle);
25109b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li
25119b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    return NO_ERROR;
25129b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li}
25139b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li
25149b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li/*
25159b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li * Do PNG Crunching on a single flag
25169b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li *  -i points to a single png file
25179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *  -o points to a single png output file
25189b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li */
25199b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Liint doSingleCrunch(Bundle* bundle)
25209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
25219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    fprintf(stdout, "Crunching single PNG file: %s\n", bundle->getSingleCrunchInputFile());
25229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    fprintf(stdout, "\tOutput file: %s\n", bundle->getSingleCrunchOutputFile());
2523a18e90176a8e2442837d0503fbfd4adb9df0818fWu-cheng Li
2524a18e90176a8e2442837d0503fbfd4adb9df0818fWu-cheng Li    String8 input(bundle->getSingleCrunchInputFile());
25259b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    String8 output(bundle->getSingleCrunchOutputFile());
25269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
25275f1e69c76ef5886ed65e303490c5f660da4756efWu-cheng Li    if (preProcessImageToCache(bundle, input, output) != NO_ERROR) {
25289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // we can't return the status_t as it gets truncate to the lower 8 bits.
25295f1e69c76ef5886ed65e303490c5f660da4756efWu-cheng Li        return 42;
25309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
25319b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li
25329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return NO_ERROR;
25339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
25349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2535a18e90176a8e2442837d0503fbfd4adb9df0818fWu-cheng Lichar CONSOLE_DATA[2925] = {
2536a18e90176a8e2442837d0503fbfd4adb9df0818fWu-cheng Li    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2537a18e90176a8e2442837d0503fbfd4adb9df0818fWu-cheng Li    32, 32, 32, 32, 32, 32, 32, 95, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32,
25389b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
25399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32,
25405f1e69c76ef5886ed65e303490c5f660da4756efWu-cheng Li    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 63,
25419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    86, 35, 40, 46, 46, 95, 95, 95, 95, 97, 97, 44, 32, 46, 124, 42, 33, 83,
25425f1e69c76ef5886ed65e303490c5f660da4756efWu-cheng Li    62, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
25439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
25449b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 46, 58, 59, 61, 59, 61, 81,
25459b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    81, 81, 81, 66, 96, 61, 61, 58, 46, 46, 46, 58, 32, 32, 32, 32, 32, 32,
25469b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32,
25479b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
25489b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    32, 32, 32, 46, 61, 59, 59, 59, 58, 106, 81, 81, 81, 81, 102, 59, 61, 59,
25499b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    59, 61, 61, 61, 58, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
25503f4639a6611222ae1ae5493de49213250d292139Wu-cheng Li    32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
25513f4639a6611222ae1ae5493de49213250d292139Wu-cheng Li    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59,
25525f1e69c76ef5886ed65e303490c5f660da4756efWu-cheng Li    59, 58, 109, 81, 81, 81, 81, 61, 59, 59, 59, 59, 59, 58, 59, 59, 46, 32,
25539b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
25545f1e69c76ef5886ed65e303490c5f660da4756efWu-cheng Li    10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
25559b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 60, 81, 81, 81, 81, 87,
25569b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    58, 59, 59, 59, 59, 59, 59, 61, 119, 44, 32, 32, 32, 32, 32, 32, 32, 32,
25579b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32,
25589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46,
25599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    47, 61, 59, 59, 58, 100, 81, 81, 81, 81, 35, 58, 59, 59, 59, 59, 59, 58,
25609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    121, 81, 91, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
25614a68e3c26dd2512c319071dc20074baa6e7d171fHai Guo    32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
25621620d118a49dc6df7b0e83d7343f8a8bb6e23b12Wu-cheng Li    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 109, 58, 59, 59, 61, 81, 81,
2563454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    81, 81, 81, 109, 58, 59, 59, 59, 59, 61, 109, 81, 81, 76, 46, 32, 32, 32,
2564454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32,
2565454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2566454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    32, 32, 32, 41, 87, 59, 61, 59, 41, 81, 81, 81, 81, 81, 81, 59, 61, 59,
2567454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    59, 58, 109, 81, 81, 87, 39, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2568454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2569454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 60, 81, 91, 59,
2570454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    59, 61, 81, 81, 81, 81, 81, 87, 43, 59, 58, 59, 60, 81, 81, 81, 76, 32,
2571454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2572454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2573454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    32, 32, 32, 32, 32, 32, 32, 32, 52, 91, 58, 45, 59, 87, 81, 81, 81, 81,
2574454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    70, 58, 58, 58, 59, 106, 81, 81, 81, 91, 32, 32, 32, 32, 32, 32, 32, 32,
2575454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32,
2576454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2577454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    32, 93, 40, 32, 46, 59, 100, 81, 81, 81, 81, 40, 58, 46, 46, 58, 100, 81,
2578454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    81, 68, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2579454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2580454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    32, 46, 46, 46, 32, 46, 46, 46, 32, 46, 32, 46, 45, 91, 59, 61, 58, 109,
2581454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    81, 81, 81, 87, 46, 58, 61, 59, 60, 81, 81, 80, 32, 32, 32, 32, 32, 32,
2582454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32,
2583454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    32, 32, 32, 32, 32, 32, 32, 46, 46, 61, 59, 61, 61, 61, 59, 61, 61, 59,
2584454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    59, 59, 58, 58, 46, 46, 41, 58, 59, 58, 81, 81, 81, 81, 69, 58, 59, 59,
2585454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    60, 81, 81, 68, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2586454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 58, 59,
2587454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    61, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 61, 46,
25885f1e69c76ef5886ed65e303490c5f660da4756efWu-cheng Li    61, 59, 93, 81, 81, 81, 81, 107, 58, 59, 58, 109, 87, 68, 96, 32, 32, 32,
2589454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2590454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    32, 32, 10, 32, 32, 32, 46, 60, 61, 61, 59, 59, 59, 59, 59, 59, 59, 59,
2591454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    59, 59, 59, 59, 59, 59, 59, 59, 59, 58, 58, 58, 115, 109, 68, 41, 36, 81,
2592454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    109, 46, 61, 61, 81, 69, 96, 46, 58, 58, 46, 58, 46, 46, 32, 32, 32, 32,
2593454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 46, 32, 95, 81,
2594454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    67, 61, 61, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
2595454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    59, 59, 59, 59, 58, 68, 39, 61, 105, 61, 63, 81, 119, 58, 106, 80, 32, 58,
2596454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    61, 59, 59, 61, 59, 61, 59, 61, 46, 95, 32, 32, 32, 32, 32, 32, 32, 32,
2597454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    32, 32, 32, 32, 32, 32, 10, 32, 32, 36, 81, 109, 105, 59, 61, 59, 59, 59,
2598454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 46, 58, 37,
2599454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    73, 108, 108, 62, 52, 81, 109, 34, 32, 61, 59, 59, 59, 59, 59, 59, 59, 59,
2600454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    59, 61, 59, 61, 61, 46, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10,
2601454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    32, 46, 45, 57, 101, 43, 43, 61, 61, 59, 59, 59, 59, 59, 59, 61, 59, 59,
2602454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    59, 59, 59, 59, 59, 59, 59, 58, 97, 46, 61, 108, 62, 126, 58, 106, 80, 96,
2603454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    46, 61, 61, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 61,
2604454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    97, 103, 97, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 45, 46, 32,
2605454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    46, 32, 32, 32, 32, 32, 32, 32, 32, 45, 45, 45, 58, 59, 59, 59, 59, 61,
2606454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    119, 81, 97, 124, 105, 124, 124, 39, 126, 95, 119, 58, 61, 58, 59, 59, 59,
2607454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 119, 81, 81, 99, 32, 32,
2608454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2609454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    32, 32, 32, 32, 32, 32, 32, 58, 59, 59, 58, 106, 81, 81, 81, 109, 119,
2610454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    119, 119, 109, 109, 81, 81, 122, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59,
2611454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    59, 59, 59, 59, 59, 58, 115, 81, 87, 81, 102, 32, 32, 32, 32, 32, 32, 10,
2612454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2613454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    32, 32, 61, 58, 59, 61, 81, 81, 81, 81, 81, 81, 87, 87, 81, 81, 81, 81,
2614454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    81, 58, 59, 59, 59, 59, 59, 59, 59, 59, 58, 45, 45, 45, 59, 59, 59, 41,
2615454630f23784afcf3dd6fc58becbb9fb6aa878a9Wu-cheng Li    87, 66, 33, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32,
26167478ea6848c0059e65a4089b4ec2ff4158520870Wu-cheng Li    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 59, 59, 93, 81,
2617da0a56df963353a1f1bd1914fa31f870d982dd5aScott Main    81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 40, 58, 59, 59, 59, 58,
2618a696f5d667227365da732481770767dcb330dd23Mathias Agopian    45, 32, 46, 32, 32, 32, 32, 32, 46, 32, 126, 96, 32, 32, 32, 32, 32, 32,
2619df4578e8ab7008a7e528d5af2ae761b33cf2bdf4Scott Main    32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
26207478ea6848c0059e65a4089b4ec2ff4158520870Wu-cheng Li    32, 32, 32, 32, 32, 32, 58, 61, 59, 58, 81, 81, 81, 81, 81, 81, 81, 81,
2621951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala    81, 81, 81, 81, 81, 40, 58, 59, 59, 59, 58, 32, 32, 32, 32, 32, 32, 32,
2622951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32,
2623951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58,
2624951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala    59, 59, 58, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 40, 58,
2625951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala    59, 59, 59, 46, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2626951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala    32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2627951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 59, 60, 81, 81, 81, 81,
2628951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala    81, 81, 81, 81, 81, 81, 81, 81, 81, 59, 61, 59, 59, 61, 32, 32, 32, 32,
2629951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2630951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala    10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2631951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala    32, 32, 32, 58, 59, 59, 93, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
2632951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala    81, 81, 40, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2633951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32,
2634951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 58, 106,
2635951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala    81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 76, 58, 59, 59, 59,
2636951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala    32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2637951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala    32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2638951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala    32, 32, 32, 32, 32, 32, 32, 61, 58, 58, 81, 81, 81, 81, 81, 81, 81, 81,
2639951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala    81, 81, 81, 81, 81, 87, 58, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32,
2640951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32,
2641951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2642951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala    58, 59, 61, 41, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 87, 59,
2643951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala    61, 58, 59, 59, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2644951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala    32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2645951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 58, 61, 81, 81, 81,
2646951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala    81, 81, 81, 81, 81, 81, 81, 81, 81, 107, 58, 59, 59, 59, 59, 58, 32, 32,
2647951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2648951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala    32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2649951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala    32, 32, 32, 32, 58, 59, 59, 58, 51, 81, 81, 81, 81, 81, 81, 81, 81, 81,
2650951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala    81, 102, 94, 59, 59, 59, 59, 59, 61, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2651951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32,
2652951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 59,
2653951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala    59, 59, 43, 63, 36, 81, 81, 81, 87, 64, 86, 102, 58, 59, 59, 59, 59, 59,
2654951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala    59, 59, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2655951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala    32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2656951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala    32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 59, 59, 59, 59, 43, 33,
2657a696f5d667227365da732481770767dcb330dd23Mathias Agopian    58, 126, 126, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 32, 46, 32, 32,
2658951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32,
26599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46,
26609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    61, 59, 59, 59, 58, 45, 58, 61, 59, 58, 58, 58, 61, 59, 59, 59, 59, 59,
26619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    59, 59, 59, 59, 59, 59, 59, 58, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32,
26629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32,
26639b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 59, 59, 58, 95,
26649b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    32, 45, 61, 59, 61, 59, 59, 59, 59, 59, 59, 59, 45, 58, 59, 59, 59, 59,
26659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    61, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
26669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
26679b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    32, 32, 58, 61, 59, 59, 59, 59, 59, 61, 59, 61, 46, 46, 32, 45, 45, 45,
26689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    59, 58, 45, 45, 46, 58, 59, 59, 59, 59, 59, 59, 61, 46, 32, 32, 32, 32,
26699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32,
26709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 58, 59, 59, 59, 59,
26713f4639a6611222ae1ae5493de49213250d292139Wu-cheng Li    59, 59, 59, 59, 59, 61, 59, 46, 32, 32, 46, 32, 46, 32, 58, 61, 59, 59,
26729b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    59, 59, 59, 59, 59, 59, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
26737478ea6848c0059e65a4089b4ec2ff4158520870Wu-cheng Li    32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
26743f4639a6611222ae1ae5493de49213250d292139Wu-cheng Li    32, 32, 32, 32, 32, 32, 32, 45, 59, 59, 59, 59, 59, 59, 59, 59, 58, 32,
26753f4639a6611222ae1ae5493de49213250d292139Wu-cheng Li    32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59, 59, 58, 32,
2676951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10,
26779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
26789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    46, 61, 59, 59, 59, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 61,
26799b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    46, 61, 59, 59, 59, 59, 59, 59, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32,
26809b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32,
26819b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59,
26829b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 32, 46, 61, 58, 59, 59, 59, 59,
2683f9293e7d5057f54ec90423f55b78138d5729e30fWu-cheng Li    59, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2684f9293e7d5057f54ec90423f55b78138d5729e30fWu-cheng Li    32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2685f9293e7d5057f54ec90423f55b78138d5729e30fWu-cheng Li    32, 32, 32, 32, 58, 59, 59, 59, 59, 59, 59, 59, 59, 46, 46, 32, 32, 32,
26869b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59, 59, 45, 32, 32, 32, 32, 32,
26873f4639a6611222ae1ae5493de49213250d292139Wu-cheng Li    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32,
26883f4639a6611222ae1ae5493de49213250d292139Wu-cheng Li    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 32, 45, 61,
26893f4639a6611222ae1ae5493de49213250d292139Wu-cheng Li    59, 59, 59, 59, 59, 58, 32, 46, 32, 32, 32, 32, 32, 32, 32, 58, 59, 59,
2690951516358e2841d2425f610bcd0175d9960135d2Eino-Ville Talvala    59, 59, 59, 58, 45, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
26919b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
26929b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 45, 45, 45, 45, 32, 46, 32,
26939b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li    32, 32, 32, 32, 32, 32, 32, 32, 32, 45, 61, 59, 58, 45, 45, 32, 32, 32,
2694eb68c46a40c773eb56ef7bcf8e7ece5c6a5a8d23Chih-Chung Chang    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2695eb68c46a40c773eb56ef7bcf8e7ece5c6a5a8d23Chih-Chung Chang    10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2696eb68c46a40c773eb56ef7bcf8e7ece5c6a5a8d23Chih-Chung Chang    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2697a696f5d667227365da732481770767dcb330dd23Mathias Agopian    32, 32, 46, 32, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2698eb68c46a40c773eb56ef7bcf8e7ece5c6a5a8d23Chih-Chung Chang    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10
2699eb68c46a40c773eb56ef7bcf8e7ece5c6a5a8d23Chih-Chung Chang  };
2700eb68c46a40c773eb56ef7bcf8e7ece5c6a5a8d23Chih-Chung Chang