Command.cpp revision 7924512aa12c6af37d90e8ccfcdf04eb78a294a3
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 "Main.h"
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "Bundle.h"
8e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn#include "ResourceFilter.h"
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "ResourceTable.h"
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "XMLNode.h"
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
123b4062eeb01be33951ba214e027da523cf09f8b1Mathias Agopian#include <utils/Log.h>
133b4062eeb01be33951ba214e027da523cf09f8b1Mathias Agopian#include <utils/threads.h>
143b4062eeb01be33951ba214e027da523cf09f8b1Mathias Agopian#include <utils/List.h>
153b4062eeb01be33951ba214e027da523cf09f8b1Mathias Agopian#include <utils/Errors.h>
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <fcntl.h>
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <errno.h>
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectusing namespace android;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Show version info.  All the cool kids do it.
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint doVersion(Bundle* bundle)
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (bundle->getFileSpecCount() != 0)
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        printf("(ignoring extra arguments)\n");
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    printf("Android Asset Packaging Tool, v0.2\n");
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return 0;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Open the file read only.  The call fails if the file doesn't exist.
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns NULL on failure.
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectZipFile* openReadOnly(const char* fileName)
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ZipFile* zip;
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    status_t result;
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    zip = new ZipFile;
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    result = zip->open(fileName, ZipFile::kOpenReadOnly);
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (result != NO_ERROR) {
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (result == NAME_NOT_FOUND)
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fprintf(stderr, "ERROR: '%s' not found\n", fileName);
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        else if (result == PERMISSION_DENIED)
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fprintf(stderr, "ERROR: '%s' access denied\n", fileName);
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        else
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fprintf(stderr, "ERROR: failed opening '%s' as Zip file\n",
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                fileName);
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        delete zip;
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return zip;
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Open the file read-write.  The file will be created if it doesn't
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * already exist and "okayToCreate" is set.
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns NULL on failure.
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectZipFile* openReadWrite(const char* fileName, bool okayToCreate)
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ZipFile* zip = NULL;
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    status_t result;
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int flags;
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    flags = ZipFile::kOpenReadWrite;
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (okayToCreate)
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        flags |= ZipFile::kOpenCreate;
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    zip = new ZipFile;
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    result = zip->open(fileName, flags);
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (result != NO_ERROR) {
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        delete zip;
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        zip = NULL;
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto bail;
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbail:
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return zip;
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return a short string describing the compression method.
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectconst char* compressionName(int method)
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (method == ZipEntry::kCompressStored)
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return "Stored";
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    else if (method == ZipEntry::kCompressDeflated)
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return "Deflated";
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    else
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return "Unknown";
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the percent reduction in size (0% == no compression).
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint calcPercent(long uncompressedLen, long compressedLen)
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!uncompressedLen)
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 0;
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    else
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return (int) (100.0 - (compressedLen * 100.0) / uncompressedLen + 0.5);
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Handle the "list" command, which can be a simple file dump or
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a verbose listing.
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The verbose listing closely matches the output of the Info-ZIP "unzip"
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * command.
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint doList(Bundle* bundle)
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int result = 1;
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ZipFile* zip = NULL;
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const ZipEntry* entry;
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    long totalUncLen, totalCompLen;
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char* zipFileName;
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (bundle->getFileSpecCount() != 1) {
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "ERROR: specify zip file name (only)\n");
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto bail;
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    zipFileName = bundle->getFileSpecEntry(0);
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    zip = openReadOnly(zipFileName);
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (zip == NULL)
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto bail;
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int count, i;
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (bundle->getVerbose()) {
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        printf("Archive:  %s\n", zipFileName);
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        printf(
145fb2a9467ad77336edbf2a1a272dbe6ec30ef8a1bKenny Root            " Length   Method    Size  Ratio   Offset      Date  Time  CRC-32    Name\n");
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        printf(
147fb2a9467ad77336edbf2a1a272dbe6ec30ef8a1bKenny Root            "--------  ------  ------- -----  -------      ----  ----  ------    ----\n");
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    totalUncLen = totalCompLen = 0;
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    count = zip->getNumEntries();
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (i = 0; i < count; i++) {
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        entry = zip->getEntryByIndex(i);
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (bundle->getVerbose()) {
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            char dateBuf[32];
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            time_t when;
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            when = entry->getModWhen();
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            strftime(dateBuf, sizeof(dateBuf), "%m-%d-%y %H:%M",
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                localtime(&when));
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
163fb2a9467ad77336edbf2a1a272dbe6ec30ef8a1bKenny Root            printf("%8ld  %-7.7s %7ld %3d%%  %8zd  %s  %08lx  %s\n",
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                (long) entry->getUncompressedLen(),
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                compressionName(entry->getCompressionMethod()),
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                (long) entry->getCompressedLen(),
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                calcPercent(entry->getUncompressedLen(),
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            entry->getCompressedLen()),
169fb2a9467ad77336edbf2a1a272dbe6ec30ef8a1bKenny Root                (size_t) entry->getLFHOffset(),
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                dateBuf,
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                entry->getCRC32(),
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                entry->getFileName());
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            printf("%s\n", entry->getFileName());
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        totalUncLen += entry->getUncompressedLen();
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        totalCompLen += entry->getCompressedLen();
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (bundle->getVerbose()) {
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        printf(
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        "--------          -------  ---                            -------\n");
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        printf("%8ld          %7ld  %2d%%                            %d files\n",
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            totalUncLen,
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            totalCompLen,
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            calcPercent(totalUncLen, totalCompLen),
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            zip->getNumEntries());
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (bundle->getAndroidList()) {
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        AssetManager assets;
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!assets.addAssetPath(String8(zipFileName), NULL)) {
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fprintf(stderr, "ERROR: list -a failed because assets could not be loaded\n");
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1977ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const ResTable& res = assets.getResources(false);
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (&res == NULL) {
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            printf("\nNo resource table found.\n");
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
202f1ff21ac62a51f5ba8ca0821ea8a90f70957e25dSteve Block#ifndef HAVE_ANDROID_OS
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            printf("\nResource table:\n");
204e17086ba346009a26cc2299b133a0fe602acb6ecDianne Hackborn            res.print(false);
205f1ff21ac62a51f5ba8ca0821ea8a90f70957e25dSteve Block#endif
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2077ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Asset* manifestAsset = assets.openNonAsset("AndroidManifest.xml",
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                   Asset::ACCESS_BUFFER);
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (manifestAsset == NULL) {
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            printf("\nNo AndroidManifest.xml found.\n");
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            printf("\nAndroid manifest:\n");
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ResXMLTree tree;
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            tree.setTo(manifestAsset->getBuffer(true),
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                       manifestAsset->getLength());
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            printXMLBlock(&tree);
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        delete manifestAsset;
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2217ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    result = 0;
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbail:
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    delete zip;
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return result;
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic ssize_t indexOfAttribute(const ResXMLTree& tree, uint32_t attrRes)
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t N = tree.getAttributeCount();
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (size_t i=0; i<N; i++) {
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (tree.getAttributeNameResID(i) == attrRes) {
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return (ssize_t)i;
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return -1;
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2401553c82e084ac5763fb393857224145506771b99Joe OnoratoString8 getAttribute(const ResXMLTree& tree, const char* ns,
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            const char* attr, String8* outError)
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ssize_t idx = tree.indexOfAttribute(ns, attr);
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (idx < 0) {
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return String8();
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Res_value value;
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (value.dataType != Res_value::TYPE_STRING) {
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (outError != NULL) *outError = "attribute is not a string value";
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return String8();
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t len;
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const uint16_t* str = tree.getAttributeStringValue(idx, &len);
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return str ? String8(str, len) : String8();
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic String8 getAttribute(const ResXMLTree& tree, uint32_t attrRes, String8* outError)
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ssize_t idx = indexOfAttribute(tree, attrRes);
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (idx < 0) {
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return String8();
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Res_value value;
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (value.dataType != Res_value::TYPE_STRING) {
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (outError != NULL) *outError = "attribute is not a string value";
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return String8();
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t len;
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const uint16_t* str = tree.getAttributeStringValue(idx, &len);
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return str ? String8(str, len) : String8();
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
277bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackbornstatic int32_t getIntegerAttribute(const ResXMLTree& tree, uint32_t attrRes,
278bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn        String8* outError, int32_t defValue = -1)
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ssize_t idx = indexOfAttribute(tree, attrRes);
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (idx < 0) {
282bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn        return defValue;
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Res_value value;
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
286bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn        if (value.dataType < Res_value::TYPE_FIRST_INT
287bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                || value.dataType > Res_value::TYPE_LAST_INT) {
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (outError != NULL) *outError = "attribute is not an integer value";
289bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn            return defValue;
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return value.data;
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
295f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackbornstatic int32_t getResolvedIntegerAttribute(const ResTable* resTable, const ResXMLTree& tree,
296f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn        uint32_t attrRes, String8* outError, int32_t defValue = -1)
297f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn{
298f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn    ssize_t idx = indexOfAttribute(tree, attrRes);
299f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn    if (idx < 0) {
300f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn        return defValue;
301f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn    }
302f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn    Res_value value;
303f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn    if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
304f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn        if (value.dataType == Res_value::TYPE_REFERENCE) {
305f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn            resTable->resolveReference(&value, 0);
306f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn        }
307f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn        if (value.dataType < Res_value::TYPE_FIRST_INT
308f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn                || value.dataType > Res_value::TYPE_LAST_INT) {
309f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn            if (outError != NULL) *outError = "attribute is not an integer value";
310f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn            return defValue;
311f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn        }
312f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn    }
313f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn    return value.data;
314f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn}
315f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic String8 getResolvedAttribute(const ResTable* resTable, const ResXMLTree& tree,
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        uint32_t attrRes, String8* outError)
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ssize_t idx = indexOfAttribute(tree, attrRes);
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (idx < 0) {
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return String8();
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Res_value value;
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (value.dataType == Res_value::TYPE_STRING) {
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            size_t len;
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            const uint16_t* str = tree.getAttributeStringValue(idx, &len);
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return str ? String8(str, len) : String8();
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        resTable->resolveReference(&value, 0);
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (value.dataType != Res_value::TYPE_STRING) {
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (outError != NULL) *outError = "attribute is not a string value";
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return String8();
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t len;
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const Res_value* value2 = &value;
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char16_t* str = const_cast<ResTable*>(resTable)->valueToString(value2, 0, NULL, &len);
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return str ? String8(str, len) : String8();
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// These are attribute resource constants for the platform, as found
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// in android.R.attr
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectenum {
345f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn    LABEL_ATTR = 0x01010001,
346f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn    ICON_ATTR = 0x01010002,
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NAME_ATTR = 0x01010003,
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    VERSION_CODE_ATTR = 0x0101021b,
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    VERSION_NAME_ATTR = 0x0101021c,
350f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn    SCREEN_ORIENTATION_ATTR = 0x0101001e,
351bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    MIN_SDK_VERSION_ATTR = 0x0101020c,
35275c498426a17b47d445711bb9e36794b05876a56Suchi Amalapurapu    MAX_SDK_VERSION_ATTR = 0x01010271,
353bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    REQ_TOUCH_SCREEN_ATTR = 0x01010227,
354bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    REQ_KEYBOARD_TYPE_ATTR = 0x01010228,
355bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    REQ_HARD_KEYBOARD_ATTR = 0x01010229,
356bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    REQ_NAVIGATION_ATTR = 0x0101022a,
357bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    REQ_FIVE_WAY_NAV_ATTR = 0x01010232,
358bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    TARGET_SDK_VERSION_ATTR = 0x01010270,
359bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    TEST_ONLY_ATTR = 0x01010272,
360a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn    ANY_DENSITY_ATTR = 0x0101026c,
361e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn    GL_ES_VERSION_ATTR = 0x01010281,
362723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn    SMALL_SCREEN_ATTR = 0x01010284,
363723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn    NORMAL_SCREEN_ATTR = 0x01010285,
364723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn    LARGE_SCREEN_ATTR = 0x01010286,
365f43489d7d5e1c0c5c9a7e54c22845fcb99765f81Dianne Hackborn    XLARGE_SCREEN_ATTR = 0x010102bf,
366e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn    REQUIRED_ATTR = 0x0101028e,
367a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn    SCREEN_SIZE_ATTR = 0x010102ca,
368a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn    SCREEN_DENSITY_ATTR = 0x010102cb,
369e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    REQUIRES_SMALLEST_WIDTH_DP_ATTR = 0x01010364,
370e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    COMPATIBLE_WIDTH_LIMIT_DP_ATTR = 0x01010365,
371e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    LARGEST_WIDTH_LIMIT_DP_ATTR = 0x01010366,
37256088a55ca6c9277f09040a7883117cb127e1e56Kenny Root    PUBLIC_KEY_ATTR = 0x010103a6,
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3757ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapuconst char *getComponentName(String8 &pkgName, String8 &componentName) {
3767ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu    ssize_t idx = componentName.find(".");
3777ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu    String8 retStr(pkgName);
3787ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu    if (idx == 0) {
3797ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu        retStr += componentName;
3807ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu    } else if (idx < 0) {
3817ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu        retStr += ".";
3827ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu        retStr += componentName;
3837ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu    } else {
3847ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu        return componentName.string();
3857ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu    }
3867ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu    return retStr.string();
3877ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu}
3887ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
389a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackbornstatic void printCompatibleScreens(ResXMLTree& tree) {
390a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn    size_t len;
391a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn    ResXMLTree::event_code_t code;
392a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn    int depth = 0;
393a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn    bool first = true;
394a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn    printf("compatible-screens:");
395a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn    while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
396a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn        if (code == ResXMLTree::END_TAG) {
397a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn            depth--;
398a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn            if (depth < 0) {
399a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn                break;
400a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn            }
401a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn            continue;
402a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn        }
403a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn        if (code != ResXMLTree::START_TAG) {
404a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn            continue;
405a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn        }
406a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn        depth++;
407a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn        String8 tag(tree.getElementName(&len));
408a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn        if (tag == "screen") {
409a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn            int32_t screenSize = getIntegerAttribute(tree,
410a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn                    SCREEN_SIZE_ATTR, NULL, -1);
411a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn            int32_t screenDensity = getIntegerAttribute(tree,
412a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn                    SCREEN_DENSITY_ATTR, NULL, -1);
413a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn            if (screenSize > 0 && screenDensity > 0) {
414a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn                if (!first) {
415a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn                    printf(",");
416a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn                }
417a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn                first = false;
418a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn                printf("'%d/%d'", screenSize, screenDensity);
419a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn            }
420a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn        }
421a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn    }
422a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn    printf("\n");
423a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn}
424a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Handle the "dump" command, to extract select data from an archive.
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
428e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrillextern char CONSOLE_DATA[2925]; // see EOF
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint doDump(Bundle* bundle)
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    status_t result = UNKNOWN_ERROR;
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Asset* asset = NULL;
4337ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (bundle->getFileSpecCount() < 1) {
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "ERROR: no dump option specified\n");
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 1;
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4387ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (bundle->getFileSpecCount() < 2) {
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "ERROR: no dump file specified\n");
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 1;
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4437ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char* option = bundle->getFileSpecEntry(0);
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char* filename = bundle->getFileSpecEntry(1);
4467ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AssetManager assets;
448bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    void* assetsCookie;
449bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    if (!assets.addAssetPath(String8(filename), &assetsCookie)) {
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "ERROR: dump failed because assets could not be loaded\n");
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 1;
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4537ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
454e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    // Make a dummy config for retrieving resources...  we need to supply
455e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    // non-default values for some configs so that we can retrieve resources
456e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    // in the app that don't have a default.  The most important of these is
457e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    // the API version because key resources like icons will have an implicit
458e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    // version if they are using newer config types like density.
459e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    ResTable_config config;
460e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    config.language[0] = 'e';
461e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    config.language[1] = 'n';
462e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    config.country[0] = 'U';
463e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    config.country[1] = 'S';
464e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    config.orientation = ResTable_config::ORIENTATION_PORT;
465e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    config.density = ResTable_config::DENSITY_MEDIUM;
466e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    config.sdkVersion = 10000; // Very high.
467e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    config.screenWidthDp = 320;
468e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    config.screenHeightDp = 480;
469e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    config.smallestScreenWidthDp = 320;
470e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    assets.setConfiguration(config);
471e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const ResTable& res = assets.getResources(false);
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (&res == NULL) {
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "ERROR: dump failed because no resource table was found\n");
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto bail;
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4777ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (strcmp("resources", option) == 0) {
479f1ff21ac62a51f5ba8ca0821ea8a90f70957e25dSteve Block#ifndef HAVE_ANDROID_OS
480e17086ba346009a26cc2299b133a0fe602acb6ecDianne Hackborn        res.print(bundle->getValues());
481f1ff21ac62a51f5ba8ca0821ea8a90f70957e25dSteve Block#endif
4826c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn
4836c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn    } else if (strcmp("strings", option) == 0) {
4846c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn        const ResStringPool* pool = res.getTableStringBlock(0);
4856c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn        printStringPool(pool);
4866c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else if (strcmp("xmltree", option) == 0) {
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (bundle->getFileSpecCount() < 3) {
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fprintf(stderr, "ERROR: no dump xmltree resource file specified\n");
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4927ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i=2; i<bundle->getFileSpecCount(); i++) {
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            const char* resname = bundle->getFileSpecEntry(i);
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ResXMLTree tree;
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            asset = assets.openNonAsset(resname, Asset::ACCESS_BUFFER);
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (asset == NULL) {
49844b283dc27ed8ba5a946d809489f29b4ae88cb15Kenny Root                fprintf(stderr, "ERROR: dump failed because resource %s found\n", resname);
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                goto bail;
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5017ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (tree.setTo(asset->getBuffer(true),
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                           asset->getLength()) != NO_ERROR) {
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                fprintf(stderr, "ERROR: Resource %s is corrupt\n", resname);
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                goto bail;
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            tree.restart();
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            printXMLBlock(&tree);
50919138468caf7050d482dc15f35a344eab11bb756Kenny Root            tree.uninit();
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            delete asset;
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            asset = NULL;
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5137ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else if (strcmp("xmlstrings", option) == 0) {
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (bundle->getFileSpecCount() < 3) {
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fprintf(stderr, "ERROR: no dump xmltree resource file specified\n");
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5197ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i=2; i<bundle->getFileSpecCount(); i++) {
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            const char* resname = bundle->getFileSpecEntry(i);
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ResXMLTree tree;
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            asset = assets.openNonAsset(resname, Asset::ACCESS_BUFFER);
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (asset == NULL) {
52544b283dc27ed8ba5a946d809489f29b4ae88cb15Kenny Root                fprintf(stderr, "ERROR: dump failed because resource %s found\n", resname);
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                goto bail;
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5287ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (tree.setTo(asset->getBuffer(true),
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                           asset->getLength()) != NO_ERROR) {
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                fprintf(stderr, "ERROR: Resource %s is corrupt\n", resname);
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                goto bail;
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            printStringPool(&tree.getStrings());
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            delete asset;
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            asset = NULL;
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5387ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ResXMLTree tree;
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        asset = assets.openNonAsset("AndroidManifest.xml",
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                            Asset::ACCESS_BUFFER);
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (asset == NULL) {
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fprintf(stderr, "ERROR: dump failed because no AndroidManifest.xml found\n");
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5477ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (tree.setTo(asset->getBuffer(true),
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                       asset->getLength()) != NO_ERROR) {
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fprintf(stderr, "ERROR: AndroidManifest.xml is corrupt\n");
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        tree.restart();
5547ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (strcmp("permissions", option) == 0) {
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            size_t len;
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ResXMLTree::event_code_t code;
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int depth = 0;
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (code == ResXMLTree::END_TAG) {
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    depth--;
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    continue;
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (code != ResXMLTree::START_TAG) {
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    continue;
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                depth++;
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                String8 tag(tree.getElementName(&len));
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                //printf("Depth %d tag %s\n", depth, tag.string());
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (depth == 1) {
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (tag != "manifest") {
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n");
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        goto bail;
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    String8 pkg = getAttribute(tree, NULL, "package", NULL);
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    printf("package: %s\n", pkg.string());
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else if (depth == 2 && tag == "permission") {
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    String8 error;
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    String8 name = getAttribute(tree, NAME_ATTR, &error);
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (error != "") {
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        fprintf(stderr, "ERROR: %s\n", error.string());
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        goto bail;
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    printf("permission: %s\n", name.string());
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else if (depth == 2 && tag == "uses-permission") {
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    String8 error;
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    String8 name = getAttribute(tree, NAME_ATTR, &error);
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (error != "") {
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        fprintf(stderr, "ERROR: %s\n", error.string());
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        goto bail;
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    printf("uses-permission: %s\n", name.string());
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (strcmp("badging", option) == 0) {
596e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            Vector<String8> locales;
597e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            res.getLocales(&locales);
598e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn
599e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            Vector<ResTable_config> configs;
600e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            res.getConfigurations(&configs);
601e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            SortedVector<int> densities;
602e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            const size_t NC = configs.size();
603e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            for (size_t i=0; i<NC; i++) {
604e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                int dens = configs[i].density;
605e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                if (dens == 0) dens = 160;
606e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                densities.add(dens);
607e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            }
608e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            size_t len;
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ResXMLTree::event_code_t code;
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int depth = 0;
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String8 error;
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bool withinActivity = false;
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bool isMainActivity = false;
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bool isLauncherActivity = false;
6161b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool isSearchable = false;
6177ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu            bool withinApplication = false;
6187ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu            bool withinReceiver = false;
6191b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool withinService = false;
6201b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool withinIntentFilter = false;
6211b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool hasMainActivity = false;
6221b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool hasOtherActivities = false;
6231b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool hasOtherReceivers = false;
6241b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool hasOtherServices = false;
6251b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool hasWallpaperService = false;
6261b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool hasImeService = false;
6271b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool hasWidgetReceivers = false;
6281b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool hasIntentFilter = false;
6291b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool actMainActivity = false;
6301b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool actWidgetReceivers = false;
6311b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool actImeService = false;
6321b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool actWallpaperService = false;
63389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill
634063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root            // These two implement the implicit permissions that are granted
635063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root            // to pre-1.6 applications.
636063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root            bool hasWriteExternalStoragePermission = false;
637063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root            bool hasReadPhoneStatePermission = false;
638063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root
6397924512aa12c6af37d90e8ccfcdf04eb78a294a3Dianne Hackborn            // If an app requests write storage, they will also get read storage.
6407924512aa12c6af37d90e8ccfcdf04eb78a294a3Dianne Hackborn            bool hasReadExternalStoragePermission = false;
6417924512aa12c6af37d90e8ccfcdf04eb78a294a3Dianne Hackborn
64289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // This next group of variables is used to implement a group of
64389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // backward-compatibility heuristics necessitated by the addition of
64489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // some new uses-feature constants in 2.1 and 2.2. In most cases, the
64589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // heuristic is "if an app requests a permission but doesn't explicitly
64689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // request the corresponding <uses-feature>, presume it's there anyway".
64789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool specCameraFeature = false; // camera-related
64889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool specCameraAutofocusFeature = false;
64989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool reqCameraAutofocusFeature = false;
65089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool reqCameraFlashFeature = false;
651e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn            bool hasCameraPermission = false;
65289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool specLocationFeature = false; // location-related
65389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool specNetworkLocFeature = false;
65489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool reqNetworkLocFeature = false;
655ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn            bool specGpsFeature = false;
65689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool reqGpsFeature = false;
65789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool hasMockLocPermission = false;
65889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool hasCoarseLocPermission = false;
659ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn            bool hasGpsPermission = false;
66089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool hasGeneralLocPermission = false;
66189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool specBluetoothFeature = false; // Bluetooth API-related
66289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool hasBluetoothPermission = false;
66389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool specMicrophoneFeature = false; // microphone-related
66489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool hasRecordAudioPermission = false;
66589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool specWiFiFeature = false;
66689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool hasWiFiPermission = false;
66789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool specTelephonyFeature = false; // telephony-related
66889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool reqTelephonySubFeature = false;
66989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool hasTelephonyPermission = false;
67089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool specTouchscreenFeature = false; // touchscreen-related
67189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool specMultitouchFeature = false;
67289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool reqDistinctMultitouchFeature = false;
673e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            bool specScreenPortraitFeature = false;
674e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            bool specScreenLandscapeFeature = false;
675f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn            bool reqScreenPortraitFeature = false;
676f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn            bool reqScreenLandscapeFeature = false;
67789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // 2.2 also added some other features that apps can request, but that
67889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // have no corresponding permission, so we cannot implement any
67989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // back-compatibility heuristic for them. The below are thus unnecessary
68089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // (but are retained here for documentary purposes.)
68189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            //bool specCompassFeature = false;
68289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            //bool specAccelerometerFeature = false;
68389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            //bool specProximityFeature = false;
68489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            //bool specAmbientLightFeature = false;
68589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            //bool specLiveWallpaperFeature = false;
68689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill
687723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            int targetSdk = 0;
688723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            int smallScreen = 1;
689723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            int normalScreen = 1;
690723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            int largeScreen = 1;
691f43489d7d5e1c0c5c9a7e54c22845fcb99765f81Dianne Hackborn            int xlargeScreen = 1;
692a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn            int anyDensity = 1;
693e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            int requiresSmallestWidthDp = 0;
694e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            int compatibleWidthLimitDp = 0;
695e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            int largestWidthLimitDp = 0;
6967ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu            String8 pkg;
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String8 activityName;
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String8 activityLabel;
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String8 activityIcon;
7007ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu            String8 receiverName;
7011b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            String8 serviceName;
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (code == ResXMLTree::END_TAG) {
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    depth--;
7051b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                    if (depth < 2) {
7061b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        withinApplication = false;
7071b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                    } else if (depth < 3) {
7081b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        if (withinActivity && isMainActivity && isLauncherActivity) {
7091b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            const char *aName = getComponentName(pkg, activityName);
710e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                            printf("launchable-activity:");
7111b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            if (aName != NULL) {
712e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                printf(" name='%s' ", aName);
7131b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            }
714e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                            printf(" label='%s' icon='%s'\n",
7151b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                                    activityLabel.string(),
7161b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                                    activityIcon.string());
7171b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        }
7181b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        if (!hasIntentFilter) {
7191b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            hasOtherActivities |= withinActivity;
7201b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            hasOtherReceivers |= withinReceiver;
7211b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            hasOtherServices |= withinService;
7221b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        }
7231b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        withinActivity = false;
7241b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        withinService = false;
7251b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        withinReceiver = false;
7261b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        hasIntentFilter = false;
7271b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        isMainActivity = isLauncherActivity = false;
7281b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                    } else if (depth < 4) {
7291b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        if (withinIntentFilter) {
7301b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            if (withinActivity) {
7311b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                                hasMainActivity |= actMainActivity;
7321b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                                hasOtherActivities |= !actMainActivity;
7331b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            } else if (withinReceiver) {
7341b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                                hasWidgetReceivers |= actWidgetReceivers;
7351b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                                hasOtherReceivers |= !actWidgetReceivers;
7361b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            } else if (withinService) {
7371b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                                hasImeService |= actImeService;
7381b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                                hasWallpaperService |= actWallpaperService;
7391b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                                hasOtherServices |= (!actImeService && !actWallpaperService);
7401b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            }
7411b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        }
7421b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        withinIntentFilter = false;
7431b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                    }
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    continue;
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (code != ResXMLTree::START_TAG) {
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    continue;
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                depth++;
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                String8 tag(tree.getElementName(&len));
7511b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                //printf("Depth %d,  %s\n", depth, tag.string());
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (depth == 1) {
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (tag != "manifest") {
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n");
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        goto bail;
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
7577ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                    pkg = getAttribute(tree, NULL, "package", NULL);
7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    printf("package: name='%s' ", pkg.string());
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    int32_t versionCode = getIntegerAttribute(tree, VERSION_CODE_ATTR, &error);
7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (error != "") {
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        fprintf(stderr, "ERROR getting 'android:versionCode' attribute: %s\n", error.string());
7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        goto bail;
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (versionCode > 0) {
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        printf("versionCode='%d' ", versionCode);
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else {
7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        printf("versionCode='' ");
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
769cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn                    String8 versionName = getResolvedAttribute(&res, tree, VERSION_NAME_ATTR, &error);
7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (error != "") {
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        fprintf(stderr, "ERROR getting 'android:versionName' attribute: %s\n", error.string());
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        goto bail;
7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    printf("versionName='%s'\n", versionName.string());
7757ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                } else if (depth == 2) {
7767ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                    withinApplication = false;
7777ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                    if (tag == "application") {
7787ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                        withinApplication = true;
779e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn
780e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                        String8 label;
781e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                        const size_t NL = locales.size();
782e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                        for (size_t i=0; i<NL; i++) {
783e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                            const char* localeStr =  locales[i].string();
784e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                            assets.setLocale(localeStr != NULL ? localeStr : "");
785e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                            String8 llabel = getResolvedAttribute(&res, tree, LABEL_ATTR, &error);
786e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                            if (llabel != "") {
787e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                if (localeStr == NULL || strlen(localeStr) == 0) {
788e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                    label = llabel;
789e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                    printf("application-label:'%s'\n", llabel.string());
790e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                } else {
791e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                    if (label == "") {
792e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                        label = llabel;
793e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                    }
794e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                    printf("application-label-%s:'%s'\n", localeStr,
795e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                            llabel.string());
796e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                }
797e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                            }
7987ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                        }
799e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn
800e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                        ResTable_config tmpConfig = config;
801e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                        const size_t ND = densities.size();
802e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                        for (size_t i=0; i<ND; i++) {
803e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                            tmpConfig.density = densities[i];
804e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                            assets.setConfiguration(tmpConfig);
805e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                            String8 icon = getResolvedAttribute(&res, tree, ICON_ATTR, &error);
806e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                            if (icon != "") {
807e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                printf("application-icon-%d:'%s'\n", densities[i], icon.string());
808e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                            }
809e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                        }
810e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                        assets.setConfiguration(config);
811e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn
8127ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                        String8 icon = getResolvedAttribute(&res, tree, ICON_ATTR, &error);
8137ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                        if (error != "") {
8147ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                            fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n", error.string());
8157ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                            goto bail;
8167ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                        }
817bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        int32_t testOnly = getIntegerAttribute(tree, TEST_ONLY_ATTR, &error, 0);
8187ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                        if (error != "") {
819bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            fprintf(stderr, "ERROR getting 'android:testOnly' attribute: %s\n", error.string());
8207ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                            goto bail;
8217ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                        }
822e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                        printf("application: label='%s' ", label.string());
823e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                        printf("icon='%s'\n", icon.string());
824bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        if (testOnly != 0) {
825bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            printf("testOnly='%d'\n", testOnly);
826bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        }
827bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                    } else if (tag == "uses-sdk") {
828bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        int32_t code = getIntegerAttribute(tree, MIN_SDK_VERSION_ATTR, &error);
829bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        if (error != "") {
830bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            error = "";
831bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            String8 name = getResolvedAttribute(&res, tree, MIN_SDK_VERSION_ATTR, &error);
832bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            if (error != "") {
833bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                                fprintf(stderr, "ERROR getting 'android:minSdkVersion' attribute: %s\n",
834bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                                        error.string());
835bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                                goto bail;
836bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            }
837723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                            if (name == "Donut") targetSdk = 4;
838bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            printf("sdkVersion:'%s'\n", name.string());
839bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        } else if (code != -1) {
840723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                            targetSdk = code;
841bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            printf("sdkVersion:'%d'\n", code);
842bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        }
84375c498426a17b47d445711bb9e36794b05876a56Suchi Amalapurapu                        code = getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR, NULL, -1);
84475c498426a17b47d445711bb9e36794b05876a56Suchi Amalapurapu                        if (code != -1) {
84575c498426a17b47d445711bb9e36794b05876a56Suchi Amalapurapu                            printf("maxSdkVersion:'%d'\n", code);
84675c498426a17b47d445711bb9e36794b05876a56Suchi Amalapurapu                        }
847bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        code = getIntegerAttribute(tree, TARGET_SDK_VERSION_ATTR, &error);
848bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        if (error != "") {
849bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            error = "";
850bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            String8 name = getResolvedAttribute(&res, tree, TARGET_SDK_VERSION_ATTR, &error);
851bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            if (error != "") {
852bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                                fprintf(stderr, "ERROR getting 'android:targetSdkVersion' attribute: %s\n",
853bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                                        error.string());
854bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                                goto bail;
855bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            }
856723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                            if (name == "Donut" && targetSdk < 4) targetSdk = 4;
857bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            printf("targetSdkVersion:'%s'\n", name.string());
858bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        } else if (code != -1) {
859723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                            if (targetSdk < code) {
860723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                                targetSdk = code;
861723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                            }
862bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            printf("targetSdkVersion:'%d'\n", code);
863bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        }
864bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                    } else if (tag == "uses-configuration") {
865bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        int32_t reqTouchScreen = getIntegerAttribute(tree,
866bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                                REQ_TOUCH_SCREEN_ATTR, NULL, 0);
867bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        int32_t reqKeyboardType = getIntegerAttribute(tree,
868bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                                REQ_KEYBOARD_TYPE_ATTR, NULL, 0);
869bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        int32_t reqHardKeyboard = getIntegerAttribute(tree,
870bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                                REQ_HARD_KEYBOARD_ATTR, NULL, 0);
871bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        int32_t reqNavigation = getIntegerAttribute(tree,
872bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                                REQ_NAVIGATION_ATTR, NULL, 0);
873bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        int32_t reqFiveWayNav = getIntegerAttribute(tree,
874bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                                REQ_FIVE_WAY_NAV_ATTR, NULL, 0);
875cb2d50d0d6e2e37ae02b014999da23ecd32038b8Dianne Hackborn                        printf("uses-configuration:");
876bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        if (reqTouchScreen != 0) {
877bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            printf(" reqTouchScreen='%d'", reqTouchScreen);
878bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        }
879bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        if (reqKeyboardType != 0) {
880bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            printf(" reqKeyboardType='%d'", reqKeyboardType);
881bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        }
882bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        if (reqHardKeyboard != 0) {
883bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            printf(" reqHardKeyboard='%d'", reqHardKeyboard);
884bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        }
885bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        if (reqNavigation != 0) {
886bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            printf(" reqNavigation='%d'", reqNavigation);
8877ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                        }
888bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        if (reqFiveWayNav != 0) {
889bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            printf(" reqFiveWayNav='%d'", reqFiveWayNav);
890bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        }
891bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        printf("\n");
892723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                    } else if (tag == "supports-screens") {
893723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                        smallScreen = getIntegerAttribute(tree,
894723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                                SMALL_SCREEN_ATTR, NULL, 1);
895723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                        normalScreen = getIntegerAttribute(tree,
896723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                                NORMAL_SCREEN_ATTR, NULL, 1);
897723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                        largeScreen = getIntegerAttribute(tree,
898723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                                LARGE_SCREEN_ATTR, NULL, 1);
899f43489d7d5e1c0c5c9a7e54c22845fcb99765f81Dianne Hackborn                        xlargeScreen = getIntegerAttribute(tree,
900f43489d7d5e1c0c5c9a7e54c22845fcb99765f81Dianne Hackborn                                XLARGE_SCREEN_ATTR, NULL, 1);
901a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn                        anyDensity = getIntegerAttribute(tree,
902a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn                                ANY_DENSITY_ATTR, NULL, 1);
903e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                        requiresSmallestWidthDp = getIntegerAttribute(tree,
904e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                REQUIRES_SMALLEST_WIDTH_DP_ATTR, NULL, 0);
905e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                        compatibleWidthLimitDp = getIntegerAttribute(tree,
906e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                COMPATIBLE_WIDTH_LIMIT_DP_ATTR, NULL, 0);
907e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                        largestWidthLimitDp = getIntegerAttribute(tree,
908e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                LARGEST_WIDTH_LIMIT_DP_ATTR, NULL, 0);
909e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                    } else if (tag == "uses-feature") {
910e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                        String8 name = getAttribute(tree, NAME_ATTR, &error);
91140b94725dc1c62ea66db0b9502dd81b97dd3e35fSuchi Amalapurapu
91240b94725dc1c62ea66db0b9502dd81b97dd3e35fSuchi Amalapurapu                        if (name != "" && error == "") {
913e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                            int req = getIntegerAttribute(tree,
914e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                                    REQUIRED_ATTR, NULL, 1);
91589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill
916e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                            if (name == "android.hardware.camera") {
917e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                                specCameraFeature = true;
91889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.hardware.camera.autofocus") {
91989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                // these have no corresponding permission to check for,
92089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                // but should imply the foundational camera permission
92189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                reqCameraAutofocusFeature = reqCameraAutofocusFeature || req;
92289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                specCameraAutofocusFeature = true;
92389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (req && (name == "android.hardware.camera.flash")) {
92489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                // these have no corresponding permission to check for,
92589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                // but should imply the foundational camera permission
92689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                reqCameraFlashFeature = true;
92789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.hardware.location") {
92889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                specLocationFeature = true;
92989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.hardware.location.network") {
93089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                specNetworkLocFeature = true;
93189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                reqNetworkLocFeature = reqNetworkLocFeature || req;
932ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn                            } else if (name == "android.hardware.location.gps") {
933ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn                                specGpsFeature = true;
93489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                reqGpsFeature = reqGpsFeature || req;
93589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.hardware.bluetooth") {
93689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                specBluetoothFeature = true;
93789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.hardware.touchscreen") {
93889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                specTouchscreenFeature = true;
93989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.hardware.touchscreen.multitouch") {
94089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                specMultitouchFeature = true;
94189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.hardware.touchscreen.multitouch.distinct") {
94289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                reqDistinctMultitouchFeature = reqDistinctMultitouchFeature || req;
94389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.hardware.microphone") {
94489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                specMicrophoneFeature = true;
94589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.hardware.wifi") {
94689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                specWiFiFeature = true;
94789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.hardware.telephony") {
94889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                specTelephonyFeature = true;
94989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (req && (name == "android.hardware.telephony.gsm" ||
95089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                               name == "android.hardware.telephony.cdma")) {
95189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                // these have no corresponding permission to check for,
95289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                // but should imply the foundational telephony permission
95389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                reqTelephonySubFeature = true;
954e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                            } else if (name == "android.hardware.screen.portrait") {
955e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                specScreenPortraitFeature = true;
956e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                            } else if (name == "android.hardware.screen.landscape") {
957e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                specScreenLandscapeFeature = true;
958e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                            }
959e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                            printf("uses-feature%s:'%s'\n",
960e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                                    req ? "" : "-not-required", name.string());
961e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                        } else {
962e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                            int vers = getIntegerAttribute(tree,
963e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                                    GL_ES_VERSION_ATTR, &error);
964e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                            if (error == "") {
965e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                                printf("uses-gl-es:'0x%x'\n", vers);
966e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                            }
967e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                        }
968e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                    } else if (tag == "uses-permission") {
969e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                        String8 name = getAttribute(tree, NAME_ATTR, &error);
97040b94725dc1c62ea66db0b9502dd81b97dd3e35fSuchi Amalapurapu                        if (name != "" && error == "") {
971e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                            if (name == "android.permission.CAMERA") {
972e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                                hasCameraPermission = true;
973ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn                            } else if (name == "android.permission.ACCESS_FINE_LOCATION") {
974ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn                                hasGpsPermission = true;
97589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.permission.ACCESS_MOCK_LOCATION") {
97689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                hasMockLocPermission = true;
97789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.permission.ACCESS_COARSE_LOCATION") {
97889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                hasCoarseLocPermission = true;
97989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" ||
98089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                       name == "android.permission.INSTALL_LOCATION_PROVIDER") {
98189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                hasGeneralLocPermission = true;
98289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.permission.BLUETOOTH" ||
98389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                       name == "android.permission.BLUETOOTH_ADMIN") {
98489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                hasBluetoothPermission = true;
98589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.permission.RECORD_AUDIO") {
98689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                hasRecordAudioPermission = true;
98789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.permission.ACCESS_WIFI_STATE" ||
98889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                       name == "android.permission.CHANGE_WIFI_STATE" ||
98989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                       name == "android.permission.CHANGE_WIFI_MULTICAST_STATE") {
99089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                hasWiFiPermission = true;
99189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.permission.CALL_PHONE" ||
99289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                       name == "android.permission.CALL_PRIVILEGED" ||
99389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                       name == "android.permission.MODIFY_PHONE_STATE" ||
99489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                       name == "android.permission.PROCESS_OUTGOING_CALLS" ||
99589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                       name == "android.permission.READ_SMS" ||
99689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                       name == "android.permission.RECEIVE_SMS" ||
99789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                       name == "android.permission.RECEIVE_MMS" ||
99889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                       name == "android.permission.RECEIVE_WAP_PUSH" ||
99989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                       name == "android.permission.SEND_SMS" ||
100089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                       name == "android.permission.WRITE_APN_SETTINGS" ||
100189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                       name == "android.permission.WRITE_SMS") {
100289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                hasTelephonyPermission = true;
1003063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root                            } else if (name == "android.permission.WRITE_EXTERNAL_STORAGE") {
1004063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root                                hasWriteExternalStoragePermission = true;
10057924512aa12c6af37d90e8ccfcdf04eb78a294a3Dianne Hackborn                            } else if (name == "android.permission.READ_EXTERNAL_STORAGE") {
10067924512aa12c6af37d90e8ccfcdf04eb78a294a3Dianne Hackborn                                hasReadExternalStoragePermission = true;
1007063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root                            } else if (name == "android.permission.READ_PHONE_STATE") {
1008063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root                                hasReadPhoneStatePermission = true;
1009e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                            }
1010e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                            printf("uses-permission:'%s'\n", name.string());
1011e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                        } else {
1012e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1013e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                                    error.string());
1014e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                            goto bail;
1015e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                        }
101643b6803095e41e6a1cf844a77813c6cdbdc84ec3Dianne Hackborn                    } else if (tag == "uses-package") {
101743b6803095e41e6a1cf844a77813c6cdbdc84ec3Dianne Hackborn                        String8 name = getAttribute(tree, NAME_ATTR, &error);
101843b6803095e41e6a1cf844a77813c6cdbdc84ec3Dianne Hackborn                        if (name != "" && error == "") {
101943b6803095e41e6a1cf844a77813c6cdbdc84ec3Dianne Hackborn                            printf("uses-package:'%s'\n", name.string());
102043b6803095e41e6a1cf844a77813c6cdbdc84ec3Dianne Hackborn                        } else {
102143b6803095e41e6a1cf844a77813c6cdbdc84ec3Dianne Hackborn                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
102243b6803095e41e6a1cf844a77813c6cdbdc84ec3Dianne Hackborn                                    error.string());
102343b6803095e41e6a1cf844a77813c6cdbdc84ec3Dianne Hackborn                                goto bail;
102443b6803095e41e6a1cf844a77813c6cdbdc84ec3Dianne Hackborn                        }
1025e2c17f9174144a6eca3fdbed8d5d1370f318f549Jeff Hamilton                    } else if (tag == "original-package") {
1026e2c17f9174144a6eca3fdbed8d5d1370f318f549Jeff Hamilton                        String8 name = getAttribute(tree, NAME_ATTR, &error);
1027e2c17f9174144a6eca3fdbed8d5d1370f318f549Jeff Hamilton                        if (name != "" && error == "") {
1028e2c17f9174144a6eca3fdbed8d5d1370f318f549Jeff Hamilton                            printf("original-package:'%s'\n", name.string());
1029e2c17f9174144a6eca3fdbed8d5d1370f318f549Jeff Hamilton                        } else {
1030e2c17f9174144a6eca3fdbed8d5d1370f318f549Jeff Hamilton                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1031e2c17f9174144a6eca3fdbed8d5d1370f318f549Jeff Hamilton                                    error.string());
1032e2c17f9174144a6eca3fdbed8d5d1370f318f549Jeff Hamilton                                goto bail;
1033e2c17f9174144a6eca3fdbed8d5d1370f318f549Jeff Hamilton                        }
1034096b67f65510a5076f1f845f9e19dda2b30ea6bbDan Morrill                    } else if (tag == "supports-gl-texture") {
10356f51fc14d0c3df8f9153ae5df992cc2731f099c8Dan Morrill                        String8 name = getAttribute(tree, NAME_ATTR, &error);
10366f51fc14d0c3df8f9153ae5df992cc2731f099c8Dan Morrill                        if (name != "" && error == "") {
1037096b67f65510a5076f1f845f9e19dda2b30ea6bbDan Morrill                            printf("supports-gl-texture:'%s'\n", name.string());
10386f51fc14d0c3df8f9153ae5df992cc2731f099c8Dan Morrill                        } else {
10396f51fc14d0c3df8f9153ae5df992cc2731f099c8Dan Morrill                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
10406f51fc14d0c3df8f9153ae5df992cc2731f099c8Dan Morrill                                    error.string());
10416f51fc14d0c3df8f9153ae5df992cc2731f099c8Dan Morrill                                goto bail;
10426f51fc14d0c3df8f9153ae5df992cc2731f099c8Dan Morrill                        }
1043a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn                    } else if (tag == "compatible-screens") {
1044a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn                        printCompatibleScreens(tree);
1045a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn                        depth--;
104656088a55ca6c9277f09040a7883117cb127e1e56Kenny Root                    } else if (tag == "package-verifier") {
104756088a55ca6c9277f09040a7883117cb127e1e56Kenny Root                        String8 name = getAttribute(tree, NAME_ATTR, &error);
104856088a55ca6c9277f09040a7883117cb127e1e56Kenny Root                        if (name != "" && error == "") {
104956088a55ca6c9277f09040a7883117cb127e1e56Kenny Root                            String8 publicKey = getAttribute(tree, PUBLIC_KEY_ATTR, &error);
105056088a55ca6c9277f09040a7883117cb127e1e56Kenny Root                            if (publicKey != "" && error == "") {
105156088a55ca6c9277f09040a7883117cb127e1e56Kenny Root                                printf("package-verifier: name='%s' publicKey='%s'\n",
105256088a55ca6c9277f09040a7883117cb127e1e56Kenny Root                                        name.string(), publicKey.string());
105356088a55ca6c9277f09040a7883117cb127e1e56Kenny Root                            }
105456088a55ca6c9277f09040a7883117cb127e1e56Kenny Root                        }
10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
10567ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                } else if (depth == 3 && withinApplication) {
10577ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                    withinActivity = false;
10587ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                    withinReceiver = false;
10591b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                    withinService = false;
10601b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                    hasIntentFilter = false;
10617ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                    if(tag == "activity") {
10627ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                        withinActivity = true;
10637ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                        activityName = getAttribute(tree, NAME_ATTR, &error);
10647ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                        if (error != "") {
10657ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", error.string());
10667ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                            goto bail;
10677ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                        }
10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10697ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                        activityLabel = getResolvedAttribute(&res, tree, LABEL_ATTR, &error);
10707ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                        if (error != "") {
10717ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                            fprintf(stderr, "ERROR getting 'android:label' attribute: %s\n", error.string());
10727ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                            goto bail;
10737ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                        }
10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10757ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                        activityIcon = getResolvedAttribute(&res, tree, ICON_ATTR, &error);
10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (error != "") {
10777ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                            fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n", error.string());
10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            goto bail;
10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
1080f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn
1081f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn                        int32_t orien = getResolvedIntegerAttribute(&res, tree,
1082f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn                                SCREEN_ORIENTATION_ATTR, &error);
1083f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn                        if (error == "") {
1084f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn                            if (orien == 0 || orien == 6 || orien == 8) {
1085f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn                                // Requests landscape, sensorLandscape, or reverseLandscape.
1086f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn                                reqScreenLandscapeFeature = true;
1087f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn                            } else if (orien == 1 || orien == 7 || orien == 9) {
1088f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn                                // Requests portrait, sensorPortrait, or reversePortrait.
1089f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn                                reqScreenPortraitFeature = true;
1090f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn                            }
1091f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn                        }
10927ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                    } else if (tag == "uses-library") {
10937ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                        String8 libraryName = getAttribute(tree, NAME_ATTR, &error);
10947ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                        if (error != "") {
10957ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                            fprintf(stderr, "ERROR getting 'android:name' attribute for uses-library: %s\n", error.string());
10967ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                            goto bail;
10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
109849237345d83e62fdb9eb8d50b13ad086636a04faDianne Hackborn                        int req = getIntegerAttribute(tree,
109949237345d83e62fdb9eb8d50b13ad086636a04faDianne Hackborn                                REQUIRED_ATTR, NULL, 1);
110049237345d83e62fdb9eb8d50b13ad086636a04faDianne Hackborn                        printf("uses-library%s:'%s'\n",
110149237345d83e62fdb9eb8d50b13ad086636a04faDianne Hackborn                                req ? "" : "-not-required", libraryName.string());
11027ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                    } else if (tag == "receiver") {
11037ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                        withinReceiver = true;
11047ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                        receiverName = getAttribute(tree, NAME_ATTR, &error);
11057ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (error != "") {
11077ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                            fprintf(stderr, "ERROR getting 'android:name' attribute for receiver: %s\n", error.string());
11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            goto bail;
11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
11101b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                    } else if (tag == "service") {
11111b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        withinService = true;
11121b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        serviceName = getAttribute(tree, NAME_ATTR, &error);
11131b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu
11141b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        if (error != "") {
11151b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            fprintf(stderr, "ERROR getting 'android:name' attribute for service: %s\n", error.string());
11161b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            goto bail;
11171b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        }
11187ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                    }
11191b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                } else if ((depth == 4) && (tag == "intent-filter")) {
11201b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                    hasIntentFilter = true;
11211b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                    withinIntentFilter = true;
11221b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                    actMainActivity = actWidgetReceivers = actImeService = actWallpaperService = false;
11231b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                } else if ((depth == 5) && withinIntentFilter){
11241b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                    String8 action;
11251b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                    if (tag == "action") {
11261b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        action = getAttribute(tree, NAME_ATTR, &error);
11271b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        if (error != "") {
11281b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", error.string());
11291b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            goto bail;
11301b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        }
11311b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        if (withinActivity) {
1132bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            if (action == "android.intent.action.MAIN") {
1133bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                                isMainActivity = true;
11341b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                                actMainActivity = true;
1135bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            }
11361b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        } else if (withinReceiver) {
11371b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            if (action == "android.appwidget.action.APPWIDGET_UPDATE") {
11381b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                                actWidgetReceivers = true;
11397ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                            }
11401b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        } else if (withinService) {
11411b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            if (action == "android.view.InputMethod") {
11421b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                                actImeService = true;
11431b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            } else if (action == "android.service.wallpaper.WallpaperService") {
11441b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                                actWallpaperService = true;
11457ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                            }
11467ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                        }
11471b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        if (action == "android.intent.action.SEARCH") {
11481b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            isSearchable = true;
11497ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                        }
11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11521b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                    if (tag == "category") {
11531b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        String8 category = getAttribute(tree, NAME_ATTR, &error);
11541b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        if (error != "") {
11551b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            fprintf(stderr, "ERROR getting 'name' attribute: %s\n", error.string());
11561b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            goto bail;
11571b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        }
11581b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        if (withinActivity) {
11591b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            if (category == "android.intent.category.LAUNCHER") {
11601b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                                isLauncherActivity = true;
11611b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            }
11621b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        }
11637ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                    }
11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1166063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root
1167063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root            // Pre-1.6 implicitly granted permission compatibility logic
1168063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root            if (targetSdk < 4) {
1169063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root                if (!hasWriteExternalStoragePermission) {
1170063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root                    printf("uses-permission:'android.permission.WRITE_EXTERNAL_STORAGE'\n");
11717924512aa12c6af37d90e8ccfcdf04eb78a294a3Dianne Hackborn                    hasWriteExternalStoragePermission = true;
1172063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root                }
1173063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root                if (!hasReadPhoneStatePermission) {
1174063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root                    printf("uses-permission:'android.permission.READ_PHONE_STATE'\n");
1175063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root                }
1176063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root            }
11771b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu
11787924512aa12c6af37d90e8ccfcdf04eb78a294a3Dianne Hackborn            // If the application has requested WRITE_EXTERNAL_STORAGE, we will
11797924512aa12c6af37d90e8ccfcdf04eb78a294a3Dianne Hackborn            // force them to always take READ_EXTERNAL_STORAGE as well.
11807924512aa12c6af37d90e8ccfcdf04eb78a294a3Dianne Hackborn            if (!hasReadExternalStoragePermission && hasWriteExternalStoragePermission) {
11817924512aa12c6af37d90e8ccfcdf04eb78a294a3Dianne Hackborn                printf("uses-permission:'android.permission.READ_EXTERNAL_STORAGE'\n");
11827924512aa12c6af37d90e8ccfcdf04eb78a294a3Dianne Hackborn            }
11837924512aa12c6af37d90e8ccfcdf04eb78a294a3Dianne Hackborn
118489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            /* The following blocks handle printing "inferred" uses-features, based
118589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill             * on whether related features or permissions are used by the app.
118689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill             * Note that the various spec*Feature variables denote whether the
118789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill             * relevant tag was *present* in the AndroidManfest, not that it was
118889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill             * present and set to true.
118989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill             */
119089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // Camera-related back-compatibility logic
119189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            if (!specCameraFeature) {
119289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                if (reqCameraFlashFeature || reqCameraAutofocusFeature) {
119389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                    // if app requested a sub-feature (autofocus or flash) and didn't
119489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                    // request the base camera feature, we infer that it meant to
119589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                    printf("uses-feature:'android.hardware.camera'\n");
119689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                } else if (hasCameraPermission) {
119789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                    // if app wants to use camera but didn't request the feature, we infer
119889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                    // that it meant to, and further that it wants autofocus
119989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                    // (which was the 1.0 - 1.5 behavior)
120089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                    printf("uses-feature:'android.hardware.camera'\n");
120189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                    if (!specCameraAutofocusFeature) {
120289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                        printf("uses-feature:'android.hardware.camera.autofocus'\n");
120389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                    }
120489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                }
1205e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn            }
1206dbe7a68cc13ae135b33769918932838d2d447169Doug Zongker
120789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // Location-related back-compatibility logic
120889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            if (!specLocationFeature &&
120989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                (hasMockLocPermission || hasCoarseLocPermission || hasGpsPermission ||
121089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                 hasGeneralLocPermission || reqNetworkLocFeature || reqGpsFeature)) {
121189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // if app either takes a location-related permission or requests one of the
121289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // sub-features, we infer that it also meant to request the base location feature
121389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                printf("uses-feature:'android.hardware.location'\n");
121489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            }
1215ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn            if (!specGpsFeature && hasGpsPermission) {
121689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // if app takes GPS (FINE location) perm but does not request the GPS
121789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // feature, we infer that it meant to
1218ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn                printf("uses-feature:'android.hardware.location.gps'\n");
1219ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn            }
122089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            if (!specNetworkLocFeature && hasCoarseLocPermission) {
122189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // if app takes Network location (COARSE location) perm but does not request the
122289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // network location feature, we infer that it meant to
122389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                printf("uses-feature:'android.hardware.location.network'\n");
122489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            }
122589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill
122689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // Bluetooth-related compatibility logic
12276b22d81aa35d9a9b32670995c002e92588b2fe09Dan Morrill            if (!specBluetoothFeature && hasBluetoothPermission && (targetSdk > 4)) {
122889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // if app takes a Bluetooth permission but does not request the Bluetooth
122989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // feature, we infer that it meant to
123089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                printf("uses-feature:'android.hardware.bluetooth'\n");
123189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            }
123289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill
123389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // Microphone-related compatibility logic
123489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            if (!specMicrophoneFeature && hasRecordAudioPermission) {
123589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // if app takes the record-audio permission but does not request the microphone
123689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // feature, we infer that it meant to
123789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                printf("uses-feature:'android.hardware.microphone'\n");
123889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            }
123989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill
124089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // WiFi-related compatibility logic
124189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            if (!specWiFiFeature && hasWiFiPermission) {
124289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // if app takes one of the WiFi permissions but does not request the WiFi
124389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // feature, we infer that it meant to
124489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                printf("uses-feature:'android.hardware.wifi'\n");
124589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            }
124689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill
124789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // Telephony-related compatibility logic
124889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            if (!specTelephonyFeature && (hasTelephonyPermission || reqTelephonySubFeature)) {
124989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // if app takes one of the telephony permissions or requests a sub-feature but
125089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // does not request the base telephony feature, we infer that it meant to
125189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                printf("uses-feature:'android.hardware.telephony'\n");
125289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            }
125389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill
125489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // Touchscreen-related back-compatibility logic
125589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            if (!specTouchscreenFeature) { // not a typo!
125689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // all apps are presumed to require a touchscreen, unless they explicitly say
125789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // <uses-feature android:name="android.hardware.touchscreen" android:required="false"/>
125889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // Note that specTouchscreenFeature is true if the tag is present, regardless
125989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // of whether its value is true or false, so this is safe
126089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                printf("uses-feature:'android.hardware.touchscreen'\n");
126189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            }
126289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            if (!specMultitouchFeature && reqDistinctMultitouchFeature) {
126389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // if app takes one of the telephony permissions or requests a sub-feature but
126489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // does not request the base telephony feature, we infer that it meant to
126589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                printf("uses-feature:'android.hardware.touchscreen.multitouch'\n");
126689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            }
1267ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn
1268e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            // Landscape/portrait-related compatibility logic
1269f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn            if (!specScreenLandscapeFeature && !specScreenPortraitFeature) {
1270f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn                // If the app has specified any activities in its manifest
1271f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn                // that request a specific orientation, then assume that
1272f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn                // orientation is required.
1273f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn                if (reqScreenLandscapeFeature) {
1274f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn                    printf("uses-feature:'android.hardware.screen.landscape'\n");
1275f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn                }
1276f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn                if (reqScreenPortraitFeature) {
1277f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn                    printf("uses-feature:'android.hardware.screen.portrait'\n");
1278f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn                }
1279e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            }
1280e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn
12811b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            if (hasMainActivity) {
12821b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                printf("main\n");
12831b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            }
12841b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            if (hasWidgetReceivers) {
12851b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                printf("app-widget\n");
12861b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            }
12871b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            if (hasImeService) {
12881b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                printf("ime\n");
12891b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            }
12901b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            if (hasWallpaperService) {
12911b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                printf("wallpaper\n");
12921b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            }
12931b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            if (hasOtherActivities) {
12941b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                printf("other-activities\n");
12951b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            }
12961b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            if (isSearchable) {
12971b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                printf("search\n");
12981b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            }
12991b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            if (hasOtherReceivers) {
13001b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                printf("other-receivers\n");
13011b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            }
13021b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            if (hasOtherServices) {
13031b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                printf("other-services\n");
13041b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            }
13051b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu
1306e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            // For modern apps, if screen size buckets haven't been specified
1307e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            // but the new width ranges have, then infer the buckets from them.
1308e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            if (smallScreen > 0 && normalScreen > 0 && largeScreen > 0 && xlargeScreen > 0
1309e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                    && requiresSmallestWidthDp > 0) {
1310e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                int compatWidth = compatibleWidthLimitDp;
1311e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                if (compatWidth <= 0) compatWidth = requiresSmallestWidthDp;
1312e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                if (requiresSmallestWidthDp <= 240 && compatWidth >= 240) {
1313e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                    smallScreen = -1;
1314e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                } else {
1315e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                    smallScreen = 0;
1316e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                }
1317e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                if (requiresSmallestWidthDp <= 320 && compatWidth >= 320) {
1318e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                    normalScreen = -1;
1319e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                } else {
1320e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                    normalScreen = 0;
1321e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                }
1322e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                if (requiresSmallestWidthDp <= 480 && compatWidth >= 480) {
1323e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                    largeScreen = -1;
1324e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                } else {
1325e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                    largeScreen = 0;
1326e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                }
1327e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                if (requiresSmallestWidthDp <= 720 && compatWidth >= 720) {
1328e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                    xlargeScreen = -1;
1329e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                } else {
1330e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                    xlargeScreen = 0;
1331e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                }
1332e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            }
1333e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn
1334723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            // Determine default values for any unspecified screen sizes,
1335723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            // based on the target SDK of the package.  As of 4 (donut)
1336723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            // the screen size support was introduced, so all default to
1337723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            // enabled.
1338723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            if (smallScreen > 0) {
1339723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                smallScreen = targetSdk >= 4 ? -1 : 0;
1340723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            }
1341723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            if (normalScreen > 0) {
1342723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                normalScreen = -1;
1343723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            }
1344723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            if (largeScreen > 0) {
1345723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                largeScreen = targetSdk >= 4 ? -1 : 0;
1346723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            }
1347f43489d7d5e1c0c5c9a7e54c22845fcb99765f81Dianne Hackborn            if (xlargeScreen > 0) {
1348d58fb97ddf052b3ceac921ac7e936af990392b2cScott Main                // Introduced in Gingerbread.
1349d58fb97ddf052b3ceac921ac7e936af990392b2cScott Main                xlargeScreen = targetSdk >= 9 ? -1 : 0;
1350f43489d7d5e1c0c5c9a7e54c22845fcb99765f81Dianne Hackborn            }
1351a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn            if (anyDensity > 0) {
1352e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                anyDensity = (targetSdk >= 4 || requiresSmallestWidthDp > 0
1353e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                        || compatibleWidthLimitDp > 0) ? -1 : 0;
1354a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn            }
1355723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            printf("supports-screens:");
1356723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            if (smallScreen != 0) printf(" 'small'");
1357723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            if (normalScreen != 0) printf(" 'normal'");
1358723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            if (largeScreen != 0) printf(" 'large'");
1359f43489d7d5e1c0c5c9a7e54c22845fcb99765f81Dianne Hackborn            if (xlargeScreen != 0) printf(" 'xlarge'");
1360723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            printf("\n");
1361a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn            printf("supports-any-density: '%s'\n", anyDensity ? "true" : "false");
1362e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            if (requiresSmallestWidthDp > 0) {
1363e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                printf("requires-smallest-width:'%d'\n", requiresSmallestWidthDp);
1364e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            }
1365e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            if (compatibleWidthLimitDp > 0) {
1366e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                printf("compatible-width-limit:'%d'\n", compatibleWidthLimitDp);
1367e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            }
1368e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            if (largestWidthLimitDp > 0) {
1369e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                printf("largest-width-limit:'%d'\n", largestWidthLimitDp);
1370e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            }
1371a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn
13729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            printf("locales:");
1373e17086ba346009a26cc2299b133a0fe602acb6ecDianne Hackborn            const size_t NL = locales.size();
1374e17086ba346009a26cc2299b133a0fe602acb6ecDianne Hackborn            for (size_t i=0; i<NL; i++) {
13759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                const char* localeStr =  locales[i].string();
13769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (localeStr == NULL || strlen(localeStr) == 0) {
13779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    localeStr = "--_--";
13789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
13799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                printf(" '%s'", localeStr);
13809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            printf("\n");
13821b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu
1383e17086ba346009a26cc2299b133a0fe602acb6ecDianne Hackborn            printf("densities:");
1384e17086ba346009a26cc2299b133a0fe602acb6ecDianne Hackborn            const size_t ND = densities.size();
1385e17086ba346009a26cc2299b133a0fe602acb6ecDianne Hackborn            for (size_t i=0; i<ND; i++) {
1386e17086ba346009a26cc2299b133a0fe602acb6ecDianne Hackborn                printf(" '%d'", densities[i]);
1387e17086ba346009a26cc2299b133a0fe602acb6ecDianne Hackborn            }
1388e17086ba346009a26cc2299b133a0fe602acb6ecDianne Hackborn            printf("\n");
13891b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu
1390bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn            AssetDir* dir = assets.openNonAssetDir(assetsCookie, "lib");
1391bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn            if (dir != NULL) {
1392bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                if (dir->getFileCount() > 0) {
1393bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                    printf("native-code:");
1394bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                    for (size_t i=0; i<dir->getFileCount(); i++) {
1395bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        printf(" '%s'", dir->getFileName(i).string());
1396bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                    }
1397bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                    printf("\n");
1398bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                }
1399bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                delete dir;
1400bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn            }
1401e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill        } else if (strcmp("badger", option) == 0) {
14026c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn            printf("%s", CONSOLE_DATA);
14039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (strcmp("configurations", option) == 0) {
14049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Vector<ResTable_config> configs;
14059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            res.getConfigurations(&configs);
14069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            const size_t N = configs.size();
14079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (size_t i=0; i<N; i++) {
14089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                printf("%s\n", configs[i].toString().string());
14099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
14119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fprintf(stderr, "ERROR: unknown dump option '%s'\n", option);
14129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
14139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    result = NO_ERROR;
14177ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
14189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbail:
14199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (asset) {
14209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        delete asset;
14219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return (result != NO_ERROR);
14239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
14249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
14279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Handle the "add" command, which wants to add files to a new or
14289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * pre-existing archive.
14299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
14309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint doAdd(Bundle* bundle)
14319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
14329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ZipFile* zip = NULL;
14339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    status_t result = UNKNOWN_ERROR;
14349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char* zipFileName;
14359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (bundle->getUpdate()) {
14379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* avoid confusion */
14389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "ERROR: can't use '-u' with add\n");
14399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto bail;
14409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (bundle->getFileSpecCount() < 1) {
14439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "ERROR: must specify zip file name\n");
14449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto bail;
14459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    zipFileName = bundle->getFileSpecEntry(0);
14479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (bundle->getFileSpecCount() < 2) {
14499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "NOTE: nothing to do\n");
14509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto bail;
14519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    zip = openReadWrite(zipFileName, true);
14549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (zip == NULL) {
14559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "ERROR: failed opening/creating '%s' as Zip file\n", zipFileName);
14569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto bail;
14579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (int i = 1; i < bundle->getFileSpecCount(); i++) {
14609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const char* fileName = bundle->getFileSpecEntry(i);
14619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (strcasecmp(String8(fileName).getPathExtension().string(), ".gz") == 0) {
14639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            printf(" '%s'... (from gzip)\n", fileName);
14649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            result = zip->addGzip(fileName, String8(fileName).getBasePath().string(), NULL);
14659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
1466dbe7a68cc13ae135b33769918932838d2d447169Doug Zongker            if (bundle->getJunkPath()) {
1467dbe7a68cc13ae135b33769918932838d2d447169Doug Zongker                String8 storageName = String8(fileName).getPathLeaf();
1468dbe7a68cc13ae135b33769918932838d2d447169Doug Zongker                printf(" '%s' as '%s'...\n", fileName, storageName.string());
1469dbe7a68cc13ae135b33769918932838d2d447169Doug Zongker                result = zip->add(fileName, storageName.string(),
1470dbe7a68cc13ae135b33769918932838d2d447169Doug Zongker                                  bundle->getCompressionMethod(), NULL);
1471dbe7a68cc13ae135b33769918932838d2d447169Doug Zongker            } else {
1472dbe7a68cc13ae135b33769918932838d2d447169Doug Zongker                printf(" '%s'...\n", fileName);
1473dbe7a68cc13ae135b33769918932838d2d447169Doug Zongker                result = zip->add(fileName, bundle->getCompressionMethod(), NULL);
1474dbe7a68cc13ae135b33769918932838d2d447169Doug Zongker            }
14759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (result != NO_ERROR) {
14779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fprintf(stderr, "Unable to add '%s' to '%s'", bundle->getFileSpecEntry(i), zipFileName);
14789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (result == NAME_NOT_FOUND)
14799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                fprintf(stderr, ": file not found\n");
14809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            else if (result == ALREADY_EXISTS)
14819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                fprintf(stderr, ": already exists in archive\n");
14829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            else
14839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                fprintf(stderr, "\n");
14849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
14859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    result = NO_ERROR;
14899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbail:
14919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    delete zip;
14929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return (result != NO_ERROR);
14939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
14949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
14979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Delete files from an existing archive.
14989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
14999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint doRemove(Bundle* bundle)
15009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
15019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ZipFile* zip = NULL;
15029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    status_t result = UNKNOWN_ERROR;
15039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char* zipFileName;
15049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (bundle->getFileSpecCount() < 1) {
15069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "ERROR: must specify zip file name\n");
15079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto bail;
15089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    zipFileName = bundle->getFileSpecEntry(0);
15109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (bundle->getFileSpecCount() < 2) {
15129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "NOTE: nothing to do\n");
15139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto bail;
15149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    zip = openReadWrite(zipFileName, false);
15179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (zip == NULL) {
15189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "ERROR: failed opening Zip archive '%s'\n",
15199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            zipFileName);
15209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto bail;
15219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (int i = 1; i < bundle->getFileSpecCount(); i++) {
15249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const char* fileName = bundle->getFileSpecEntry(i);
15259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ZipEntry* entry;
15269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        entry = zip->getEntryByName(fileName);
15289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (entry == NULL) {
15299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            printf(" '%s' NOT FOUND\n", fileName);
15309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            continue;
15319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        result = zip->remove(entry);
15349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (result != NO_ERROR) {
15369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fprintf(stderr, "Unable to delete '%s' from '%s'\n",
15379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                bundle->getFileSpecEntry(i), zipFileName);
15389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
15399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* update the archive */
15439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    zip->flush();
15449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbail:
15469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    delete zip;
15479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return (result != NO_ERROR);
15489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
15499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
15529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Package up an asset directory and associated application files.
15539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
15549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint doPackage(Bundle* bundle)
15559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
15569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char* outputAPKFile;
15579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int retVal = 1;
15589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    status_t err;
15599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sp<AaptAssets> assets;
15609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int N;
15619bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin    FILE* fp;
15629bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin    String8 dependencyFile;
15639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // -c zz_ZZ means do pseudolocalization
15659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ResourceFilter filter;
15669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    err = filter.parse(bundle->getConfigurations());
15679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (err != NO_ERROR) {
15689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto bail;
15699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (filter.containsPseudo()) {
15719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bundle->setPseudolocalize(true);
15729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    N = bundle->getFileSpecCount();
15759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (N < 1 && bundle->getResourceSourceDirs().size() == 0 && bundle->getJarFiles().size() == 0
15769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            && bundle->getAndroidManifestFile() == NULL && bundle->getAssetSourceDir() == NULL) {
15779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "ERROR: no input files\n");
15789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto bail;
15799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    outputAPKFile = bundle->getOutputAPKFile();
15829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Make sure the filenames provided exist and are of the appropriate type.
15849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (outputAPKFile) {
15859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        FileType type;
15869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        type = getFileType(outputAPKFile);
15879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (type != kFileTypeNonexistent && type != kFileTypeRegular) {
15889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fprintf(stderr,
15899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                "ERROR: output file '%s' exists but is not regular file\n",
15909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                outputAPKFile);
15919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
15929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Load the assets.
15969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assets = new AaptAssets();
15979bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin
159803589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin    // Set up the resource gathering in assets if we're going to generate
1599b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin    // dependency files. Every time we encounter a resource while slurping
1600b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin    // the tree, we'll add it to these stores so we have full resource paths
1601b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin    // to write to a dependency file.
16029bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin    if (bundle->getGenDependencies()) {
160303589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        sp<FilePathStore> resPathStore = new FilePathStore;
160403589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        assets->setFullResPaths(resPathStore);
160503589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        sp<FilePathStore> assetPathStore = new FilePathStore;
160603589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        assets->setFullAssetPaths(assetPathStore);
16079bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin    }
16089bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin
16099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    err = assets->slurpFromArgs(bundle);
16109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (err < 0) {
16119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto bail;
16129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (bundle->getVerbose()) {
1615e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn        assets->print(String8());
16169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16189bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin    // If they asked for any fileAs that need to be compiled, do so.
16199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (bundle->getResourceSourceDirs().size() || bundle->getAndroidManifestFile()) {
16209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        err = buildResources(bundle, assets);
16219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (err != 0) {
16229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
16239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // At this point we've read everything and processed everything.  From here
16279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // on out it's just writing output files.
16289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (SourcePos::hasErrors()) {
16299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto bail;
16309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16321644c6d7f4931d0b4fe7ea77c63b016af01a46d3Dianne Hackborn    // Update symbols with information about which ones are needed as Java symbols.
16331644c6d7f4931d0b4fe7ea77c63b016af01a46d3Dianne Hackborn    assets->applyJavaSymbols();
16341644c6d7f4931d0b4fe7ea77c63b016af01a46d3Dianne Hackborn    if (SourcePos::hasErrors()) {
16351644c6d7f4931d0b4fe7ea77c63b016af01a46d3Dianne Hackborn        goto bail;
16361644c6d7f4931d0b4fe7ea77c63b016af01a46d3Dianne Hackborn    }
16371644c6d7f4931d0b4fe7ea77c63b016af01a46d3Dianne Hackborn
1638b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin    // If we've been asked to generate a dependency file, do that here
16399bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin    if (bundle->getGenDependencies()) {
1640b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin        // If this is the packaging step, generate the dependency file next to
1641b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin        // the output apk (e.g. bin/resources.ap_.d)
164203589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        if (outputAPKFile) {
164303589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin            dependencyFile = String8(outputAPKFile);
1644b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin            // Add the .d extension to the dependency file.
164503589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin            dependencyFile.append(".d");
164603589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        } else {
1647b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin            // Else if this is the R.java dependency generation step,
1648b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin            // generate the dependency file in the R.java package subdirectory
1649b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin            // e.g. gen/com/foo/app/R.java.d
165003589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin            dependencyFile = String8(bundle->getRClassDir());
1651b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin            dependencyFile.appendPath("R.java.d");
165203589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        }
16539bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin        // Make sure we have a clean dependency file to start with
16549bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin        fp = fopen(dependencyFile, "w");
16559bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin        fclose(fp);
16569bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin    }
16579bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin
16589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Write out R.java constants
16591644c6d7f4931d0b4fe7ea77c63b016af01a46d3Dianne Hackborn    if (!assets->havePrivateSymbols()) {
166063459ad555c10de1f316d6de01fc3cd0c0aaa457Xavier Ducrohet        if (bundle->getCustomPackage() == NULL) {
1661b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin            // Write the R.java file into the appropriate class directory
1662b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin            // e.g. gen/com/foo/app/R.java
166363459ad555c10de1f316d6de01fc3cd0c0aaa457Xavier Ducrohet            err = writeResourceSymbols(bundle, assets, assets->getPackage(), true);
1664b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin            // If we have library files, we're going to write our R.java file into
1665b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin            // the appropriate class directory for those libraries as well.
1666b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin            // e.g. gen/com/foo/app/lib/R.java
1667ce89f1531ed8b96b8b790b3f8b18dd4cf483f7f0Josiah Gaskin            if (bundle->getExtraPackages() != NULL) {
16689bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin                // Split on colon
1669ce89f1531ed8b96b8b790b3f8b18dd4cf483f7f0Josiah Gaskin                String8 libs(bundle->getExtraPackages());
16709bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin                char* packageString = strtok(libs.lockBuffer(libs.length()), ":");
1671ce89f1531ed8b96b8b790b3f8b18dd4cf483f7f0Josiah Gaskin                while (packageString != NULL) {
1672b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin                    // Write the R.java file out with the correct package name
1673ce89f1531ed8b96b8b790b3f8b18dd4cf483f7f0Josiah Gaskin                    err = writeResourceSymbols(bundle, assets, String8(packageString), true);
16749bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin                    packageString = strtok(NULL, ":");
1675ce89f1531ed8b96b8b790b3f8b18dd4cf483f7f0Josiah Gaskin                }
1676ce89f1531ed8b96b8b790b3f8b18dd4cf483f7f0Josiah Gaskin                libs.unlockBuffer();
1677ce89f1531ed8b96b8b790b3f8b18dd4cf483f7f0Josiah Gaskin            }
167863459ad555c10de1f316d6de01fc3cd0c0aaa457Xavier Ducrohet        } else {
167963459ad555c10de1f316d6de01fc3cd0c0aaa457Xavier Ducrohet            const String8 customPkg(bundle->getCustomPackage());
168063459ad555c10de1f316d6de01fc3cd0c0aaa457Xavier Ducrohet            err = writeResourceSymbols(bundle, assets, customPkg, true);
168163459ad555c10de1f316d6de01fc3cd0c0aaa457Xavier Ducrohet        }
16829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (err < 0) {
16839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
16849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
16869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        err = writeResourceSymbols(bundle, assets, assets->getPackage(), false);
16879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (err < 0) {
16889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
16899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        err = writeResourceSymbols(bundle, assets, assets->getSymbolsPrivatePackage(), true);
16919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (err < 0) {
16929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
16939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16961553c82e084ac5763fb393857224145506771b99Joe Onorato    // Write out the ProGuard file
16971553c82e084ac5763fb393857224145506771b99Joe Onorato    err = writeProguardFile(bundle, assets);
16981553c82e084ac5763fb393857224145506771b99Joe Onorato    if (err < 0) {
16991553c82e084ac5763fb393857224145506771b99Joe Onorato        goto bail;
17001553c82e084ac5763fb393857224145506771b99Joe Onorato    }
17011553c82e084ac5763fb393857224145506771b99Joe Onorato
17029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Write the apk
17039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (outputAPKFile) {
17049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        err = writeAPK(bundle, assets, String8(outputAPKFile));
17059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (err != NO_ERROR) {
17069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fprintf(stderr, "ERROR: packaging of '%s' failed\n", outputAPKFile);
17079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
17089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1711b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin    // If we've been asked to generate a dependency file, we need to finish up here.
1712b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin    // the writeResourceSymbols and writeAPK functions have already written the target
1713b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin    // half of the dependency file, now we need to write the prerequisites. (files that
1714b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin    // the R.java file or .ap_ file depend on)
171503589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin    if (bundle->getGenDependencies()) {
171603589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        // Now that writeResourceSymbols or writeAPK has taken care of writing
171703589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        // the targets to our dependency file, we'll write the prereqs
171803589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        fp = fopen(dependencyFile, "a+");
171903589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        fprintf(fp, " : ");
172003589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        bool includeRaw = (outputAPKFile != NULL);
172103589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        err = writeDependencyPreReqs(bundle, assets, fp, includeRaw);
1722b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin        // Also manually add the AndroidManifeset since it's not under res/ or assets/
1723b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin        // and therefore was not added to our pathstores during slurping
172403589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        fprintf(fp, "%s \\\n", bundle->getAndroidManifestFile());
172503589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        fclose(fp);
172603589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin    }
172703589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin
17289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    retVal = 0;
17299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbail:
17309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (SourcePos::hasErrors()) {
17319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SourcePos::printErrors(stderr);
17329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return retVal;
17349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
17358a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
17368a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin/*
17378a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin * Do PNG Crunching
17388a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin * PRECONDITIONS
17398a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin *  -S flag points to a source directory containing drawable* folders
17408a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin *  -C flag points to destination directory. The folder structure in the
17418a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin *     source directory will be mirrored to the destination (cache) directory
17428a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin *
17438a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin * POSTCONDITIONS
17448a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin *  Destination directory will be updated to match the PNG files in
17458a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin *  the source directory.
17468a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin */
17478a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskinint doCrunch(Bundle* bundle)
17488a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin{
17498a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    fprintf(stdout, "Crunching PNG Files in ");
17508a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    fprintf(stdout, "source dir: %s\n", bundle->getResourceSourceDirs()[0]);
17518a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    fprintf(stdout, "To destination dir: %s\n", bundle->getCrunchedOutputDir());
17528a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
17538a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    updatePreProcessedCache(bundle);
17548a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
17558a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    return NO_ERROR;
17568a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin}
1757e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill
1758e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrillchar CONSOLE_DATA[2925] = {
1759e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1760e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 95, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1761e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1762e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32,
1763e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 63,
1764e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    86, 35, 40, 46, 46, 95, 95, 95, 95, 97, 97, 44, 32, 46, 124, 42, 33, 83,
1765e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    62, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1766e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1767e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 46, 58, 59, 61, 59, 61, 81,
1768e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    81, 81, 81, 66, 96, 61, 61, 58, 46, 46, 46, 58, 32, 32, 32, 32, 32, 32,
1769e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32,
1770e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1771e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 46, 61, 59, 59, 59, 58, 106, 81, 81, 81, 81, 102, 59, 61, 59,
1772e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 61, 61, 61, 58, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1773e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1774e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59,
1775e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 58, 109, 81, 81, 81, 81, 61, 59, 59, 59, 59, 59, 58, 59, 59, 46, 32,
1776e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1777e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1778e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 60, 81, 81, 81, 81, 87,
1779e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    58, 59, 59, 59, 59, 59, 59, 61, 119, 44, 32, 32, 32, 32, 32, 32, 32, 32,
1780e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32,
1781e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46,
1782e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    47, 61, 59, 59, 58, 100, 81, 81, 81, 81, 35, 58, 59, 59, 59, 59, 59, 58,
1783e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    121, 81, 91, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1784e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1785e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 109, 58, 59, 59, 61, 81, 81,
1786e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    81, 81, 81, 109, 58, 59, 59, 59, 59, 61, 109, 81, 81, 76, 46, 32, 32, 32,
1787e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32,
1788e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1789e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 41, 87, 59, 61, 59, 41, 81, 81, 81, 81, 81, 81, 59, 61, 59,
1790e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 58, 109, 81, 81, 87, 39, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1791e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1792e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 60, 81, 91, 59,
1793e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 61, 81, 81, 81, 81, 81, 87, 43, 59, 58, 59, 60, 81, 81, 81, 76, 32,
1794e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1795e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1796e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 52, 91, 58, 45, 59, 87, 81, 81, 81, 81,
1797e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    70, 58, 58, 58, 59, 106, 81, 81, 81, 91, 32, 32, 32, 32, 32, 32, 32, 32,
1798e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32,
1799e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1800e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 93, 40, 32, 46, 59, 100, 81, 81, 81, 81, 40, 58, 46, 46, 58, 100, 81,
1801e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    81, 68, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1802e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1803e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 46, 46, 46, 32, 46, 46, 46, 32, 46, 32, 46, 45, 91, 59, 61, 58, 109,
1804e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    81, 81, 81, 87, 46, 58, 61, 59, 60, 81, 81, 80, 32, 32, 32, 32, 32, 32,
1805e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32,
1806e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 46, 46, 61, 59, 61, 61, 61, 59, 61, 61, 59,
1807e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 58, 58, 46, 46, 41, 58, 59, 58, 81, 81, 81, 81, 69, 58, 59, 59,
1808e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    60, 81, 81, 68, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1809e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 58, 59,
1810e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    61, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 61, 46,
1811e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    61, 59, 93, 81, 81, 81, 81, 107, 58, 59, 58, 109, 87, 68, 96, 32, 32, 32,
1812e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1813e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 10, 32, 32, 32, 46, 60, 61, 61, 59, 59, 59, 59, 59, 59, 59, 59,
1814e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 59, 59, 59, 59, 59, 59, 59, 58, 58, 58, 115, 109, 68, 41, 36, 81,
1815e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    109, 46, 61, 61, 81, 69, 96, 46, 58, 58, 46, 58, 46, 46, 32, 32, 32, 32,
1816e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 46, 32, 95, 81,
1817e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    67, 61, 61, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
1818e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 59, 59, 58, 68, 39, 61, 105, 61, 63, 81, 119, 58, 106, 80, 32, 58,
1819e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    61, 59, 59, 61, 59, 61, 59, 61, 46, 95, 32, 32, 32, 32, 32, 32, 32, 32,
1820e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 10, 32, 32, 36, 81, 109, 105, 59, 61, 59, 59, 59,
1821e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 46, 58, 37,
1822e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    73, 108, 108, 62, 52, 81, 109, 34, 32, 61, 59, 59, 59, 59, 59, 59, 59, 59,
1823e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 61, 59, 61, 61, 46, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10,
1824e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 46, 45, 57, 101, 43, 43, 61, 61, 59, 59, 59, 59, 59, 59, 61, 59, 59,
1825e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 59, 59, 59, 59, 59, 58, 97, 46, 61, 108, 62, 126, 58, 106, 80, 96,
1826e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    46, 61, 61, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 61,
1827e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    97, 103, 97, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 45, 46, 32,
1828e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    46, 32, 32, 32, 32, 32, 32, 32, 32, 45, 45, 45, 58, 59, 59, 59, 59, 61,
1829e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    119, 81, 97, 124, 105, 124, 124, 39, 126, 95, 119, 58, 61, 58, 59, 59, 59,
1830e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 119, 81, 81, 99, 32, 32,
1831e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1832e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 58, 59, 59, 58, 106, 81, 81, 81, 109, 119,
1833e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    119, 119, 109, 109, 81, 81, 122, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59,
1834e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 59, 59, 59, 58, 115, 81, 87, 81, 102, 32, 32, 32, 32, 32, 32, 10,
1835e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1836e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 61, 58, 59, 61, 81, 81, 81, 81, 81, 81, 87, 87, 81, 81, 81, 81,
1837e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    81, 58, 59, 59, 59, 59, 59, 59, 59, 59, 58, 45, 45, 45, 59, 59, 59, 41,
1838e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    87, 66, 33, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32,
1839e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 59, 59, 93, 81,
1840e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 40, 58, 59, 59, 59, 58,
1841e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    45, 32, 46, 32, 32, 32, 32, 32, 46, 32, 126, 96, 32, 32, 32, 32, 32, 32,
1842e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1843e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 58, 61, 59, 58, 81, 81, 81, 81, 81, 81, 81, 81,
1844e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    81, 81, 81, 81, 81, 40, 58, 59, 59, 59, 58, 32, 32, 32, 32, 32, 32, 32,
1845e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32,
1846e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58,
1847e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 58, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 40, 58,
1848e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 59, 46, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1849e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1850e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 59, 60, 81, 81, 81, 81,
1851e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    81, 81, 81, 81, 81, 81, 81, 81, 81, 59, 61, 59, 59, 61, 32, 32, 32, 32,
1852e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1853e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1854e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 58, 59, 59, 93, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
1855e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    81, 81, 40, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1856e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32,
1857e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 58, 106,
1858e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 76, 58, 59, 59, 59,
1859e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1860e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1861e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 61, 58, 58, 81, 81, 81, 81, 81, 81, 81, 81,
1862e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    81, 81, 81, 81, 81, 87, 58, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32,
1863e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32,
1864e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1865e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    58, 59, 61, 41, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 87, 59,
1866e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    61, 58, 59, 59, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1867e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1868e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 58, 61, 81, 81, 81,
1869e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    81, 81, 81, 81, 81, 81, 81, 81, 81, 107, 58, 59, 59, 59, 59, 58, 32, 32,
1870e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1871e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1872e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 58, 59, 59, 58, 51, 81, 81, 81, 81, 81, 81, 81, 81, 81,
1873e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    81, 102, 94, 59, 59, 59, 59, 59, 61, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1874e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32,
1875e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 59,
1876e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 43, 63, 36, 81, 81, 81, 87, 64, 86, 102, 58, 59, 59, 59, 59, 59,
1877e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1878e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1879e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 59, 59, 59, 59, 43, 33,
1880e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    58, 126, 126, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 32, 46, 32, 32,
1881e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32,
1882e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46,
1883e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    61, 59, 59, 59, 58, 45, 58, 61, 59, 58, 58, 58, 61, 59, 59, 59, 59, 59,
1884e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 59, 59, 59, 59, 59, 58, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32,
1885e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32,
1886e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 59, 59, 58, 95,
1887e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 45, 61, 59, 61, 59, 59, 59, 59, 59, 59, 59, 45, 58, 59, 59, 59, 59,
1888e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    61, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1889e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1890e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 58, 61, 59, 59, 59, 59, 59, 61, 59, 61, 46, 46, 32, 45, 45, 45,
1891e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 58, 45, 45, 46, 58, 59, 59, 59, 59, 59, 59, 61, 46, 32, 32, 32, 32,
1892e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32,
1893e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 58, 59, 59, 59, 59,
1894e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 59, 59, 59, 61, 59, 46, 32, 32, 46, 32, 46, 32, 58, 61, 59, 59,
1895e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 59, 59, 59, 59, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1896e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1897e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 45, 59, 59, 59, 59, 59, 59, 59, 59, 58, 32,
1898e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59, 59, 58, 32,
1899e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10,
1900e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1901e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    46, 61, 59, 59, 59, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 61,
1902e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    46, 61, 59, 59, 59, 59, 59, 59, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1903e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32,
1904e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59,
1905e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 32, 46, 61, 58, 59, 59, 59, 59,
1906e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1907e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1908e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 58, 59, 59, 59, 59, 59, 59, 59, 59, 46, 46, 32, 32, 32,
1909e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59, 59, 45, 32, 32, 32, 32, 32,
1910e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32,
1911e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 32, 45, 61,
1912e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 59, 59, 59, 58, 32, 46, 32, 32, 32, 32, 32, 32, 32, 58, 59, 59,
1913e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 59, 58, 45, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1914e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1915e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 45, 45, 45, 45, 32, 46, 32,
1916e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 45, 61, 59, 58, 45, 45, 32, 32, 32,
1917e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1918e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1919e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1920e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 46, 32, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1921e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10
1922e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill  };
1923